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 GmbH & Co. KG, 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.file.types; 029 030import org.opencms.configuration.CmsConfigurationCopyResource; 031import org.opencms.configuration.CmsConfigurationException; 032import org.opencms.configuration.CmsParameterConfiguration; 033import org.opencms.db.CmsSecurityManager; 034import org.opencms.file.CmsFile; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsProperty; 037import org.opencms.file.CmsResource; 038import org.opencms.file.CmsResourceFilter; 039import org.opencms.file.CmsVfsException; 040import org.opencms.file.CmsVfsResourceNotFoundException; 041import org.opencms.loader.CmsLoaderException; 042import org.opencms.loader.CmsResourceManager; 043import org.opencms.lock.CmsLockType; 044import org.opencms.main.CmsException; 045import org.opencms.main.CmsIllegalArgumentException; 046import org.opencms.main.CmsLog; 047import org.opencms.main.CmsRuntimeException; 048import org.opencms.main.OpenCms; 049import org.opencms.relations.CmsLink; 050import org.opencms.relations.I_CmsLinkParseable; 051import org.opencms.report.I_CmsReport; 052import org.opencms.staticexport.CmsLinkManager; 053import org.opencms.util.CmsFileUtil; 054import org.opencms.util.CmsMacroResolver; 055import org.opencms.util.CmsStringUtil; 056import org.opencms.xml.containerpage.CmsFormatterConfiguration; 057 058import java.util.ArrayList; 059import java.util.Collections; 060import java.util.HashMap; 061import java.util.Iterator; 062import java.util.List; 063import java.util.Map; 064 065import org.apache.commons.logging.Log; 066 067/** 068 * Base implementation for resource type classes.<p> 069 * 070 * @since 6.0.0 071 */ 072public abstract class A_CmsResourceType implements I_CmsResourceType { 073 074 /** Configuration key for optional javascript in galleries. */ 075 public static final String CONFIGURATION_GALLERY_JAVASCRIPT_PATH = "gallery.javascript.path"; 076 077 /** Configuration key for optional preview provider in galleries. */ 078 public static final String CONFIGURATION_GALLERY_PREVIEW_PROVIDER = "gallery.preview.provider"; 079 080 /** Configuration key for the optional folder class name. */ 081 public static final String CONFIGURATION_GALLERY_TYPE_NAMES = "gallery.type.names"; 082 083 /** Configuration key for the (optional) internal flag. */ 084 public static final String CONFIGURATION_INTERNAL = "resource.flag.internal"; 085 086 /** The default gallery preview provider. */ 087 public static final String DEFAULT_GALLERY_PREVIEW_PROVIDER = "org.opencms.ade.galleries.preview.CmsBinaryPreviewProvider"; 088 089 /** Macro for the folder path of the current resource. */ 090 public static final String MACRO_RESOURCE_FOLDER_PATH = "resource.folder.path"; 091 092 /** Macro for the folder path of the current resource, with touch enabled for the copied resources. */ 093 public static final String MACRO_RESOURCE_FOLDER_PATH_TOUCH = "resource.folder.path.touch"; 094 095 /** Macro for the name of the current resource. */ 096 public static final String MACRO_RESOURCE_NAME = "resource.name"; 097 098 /** Macro for the parent folder path of the current resource. */ 099 public static final String MACRO_RESOURCE_PARENT_PATH = "resource.parent.path"; 100 101 /** Macro for the root path of the current resource. */ 102 public static final String MACRO_RESOURCE_ROOT_PATH = "resource.root.path"; 103 104 /** Macro for the site path of the current resource. */ 105 public static final String MACRO_RESOURCE_SITE_PATH = "resource.site.path"; 106 107 /** The log object for this class. */ 108 private static final Log LOG = CmsLog.getLog(A_CmsResourceType.class); 109 110 /** The serial version id. */ 111 private static final long serialVersionUID = 2131071233840674874L; 112 113 /** Flag for showing that this is an additional resource type which is defined in a module. */ 114 protected boolean m_addititionalModuleResourceType; 115 116 /** The configured class name of this resource type. */ 117 protected String m_className; 118 119 /** Configuration parameters. */ 120 protected CmsParameterConfiguration m_configuration; 121 122 /** The list of resources to copy. */ 123 protected List<CmsConfigurationCopyResource> m_copyResources; 124 125 /** The list of configured default properties. */ 126 protected List<CmsProperty> m_defaultProperties; 127 128 /** Indicates that the configuration of the resource type has been frozen. */ 129 protected boolean m_frozen; 130 131 /** The gallery preview provider. */ 132 protected String m_galleryPreviewProvider; 133 134 /** Contains the file extensions mapped to this resource type. */ 135 protected List<String> m_mappings; 136 137 /** The module name if this is an additional resource type which is defined in a module. */ 138 protected String m_moduleName; 139 140 /** The configured id of this resource type. */ 141 protected int m_typeId; 142 143 /** The configured name of this resource type. */ 144 protected String m_typeName; 145 146 /** The folder for which links should be adjusted after copying the copy-resources. */ 147 private String m_adjustLinksFolder; 148 149 /** The gallery type name for this resource type. */ 150 private String m_galleryTypeNames; 151 152 /** The gallery type for this resource type. */ 153 private List<I_CmsResourceType> m_galleryTypes; 154 155 /** The optional internal parameter value. */ 156 private Boolean m_internal; 157 158 /** 159 * Default constructor, used to initialize some member variables.<p> 160 */ 161 public A_CmsResourceType() { 162 163 m_typeId = -1; 164 m_mappings = new ArrayList<String>(); 165 m_defaultProperties = new ArrayList<CmsProperty>(); 166 m_copyResources = new ArrayList<CmsConfigurationCopyResource>(); 167 m_configuration = new CmsParameterConfiguration(); 168 } 169 170 /** 171 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 172 */ 173 public void addConfigurationParameter(String paramName, String paramValue) { 174 175 m_configuration.add(paramName, paramValue); 176 if (CmsStringUtil.isNotEmpty(paramName) && CmsStringUtil.isNotEmpty(paramValue)) { 177 if (CONFIGURATION_INTERNAL.equalsIgnoreCase(paramName)) { 178 m_internal = Boolean.valueOf(paramValue.trim()); 179 } 180 if (CONFIGURATION_GALLERY_TYPE_NAMES.equalsIgnoreCase(paramName)) { 181 m_galleryTypeNames = paramValue.trim(); 182 } 183 } 184 } 185 186 /** 187 * Adds a new "copy resource" to this resource type, 188 * allowed only during the configuration phase.<p> 189 * 190 * The "copy resources" are copied to the specified location after 191 * a new resource of this type is created. Usually this feature is used to 192 * populate a newly created folder with some default resources.<p> 193 * 194 * If target is <code>null</code>, the macro {@link #MACRO_RESOURCE_FOLDER_PATH} is used as default. 195 * If type is <code>null</code>, the copy type {@link CmsResource#COPY_AS_NEW} is used as default.<p> 196 * 197 * @param source the source resource 198 * @param target the target resource (may contain macros) 199 * @param type the type of the copy, for example "as new", "as sibling" etc 200 * 201 * @throws CmsConfigurationException if the configuration is already frozen 202 */ 203 public void addCopyResource(String source, String target, String type) throws CmsConfigurationException { 204 205 if (LOG.isDebugEnabled()) { 206 LOG.debug( 207 Messages.get().getBundle().key( 208 Messages.LOG_ADD_COPY_RESOURCE_4, 209 new Object[] {this, source, target, type})); 210 } 211 212 if (m_frozen) { 213 // configuration already frozen 214 throw new CmsConfigurationException( 215 Messages.get().container( 216 Messages.ERR_CONFIG_FROZEN_3, 217 this.getClass().getName(), 218 getTypeName(), 219 Integer.valueOf(getTypeId()))); 220 } 221 222 // create the copy resource object an add it to the list 223 CmsConfigurationCopyResource copyResource = new CmsConfigurationCopyResource(source, target, type); 224 m_copyResources.add(copyResource); 225 } 226 227 /** 228 * Adds a default property to this resource type, 229 * allowed only during the configuration phase.<p> 230 * 231 * @param property the default property to add 232 * 233 * @throws CmsConfigurationException if the configuration is already frozen 234 */ 235 public void addDefaultProperty(CmsProperty property) throws CmsConfigurationException { 236 237 if (LOG.isDebugEnabled()) { 238 LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_DFLT_PROP_2, this, property)); 239 } 240 241 if (m_frozen) { 242 // configuration already frozen 243 throw new CmsConfigurationException( 244 Messages.get().container( 245 Messages.ERR_CONFIG_FROZEN_3, 246 this.getClass().getName(), 247 getTypeName(), 248 Integer.valueOf(getTypeId()))); 249 } 250 251 m_defaultProperties.add(property); 252 } 253 254 /** 255 * @see org.opencms.file.types.I_CmsResourceType#addMappingType(java.lang.String) 256 */ 257 public void addMappingType(String mapping) { 258 259 // this configuration does not support parameters 260 if (LOG.isDebugEnabled()) { 261 LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_MAPPING_TYPE_2, mapping, this)); 262 } 263 if (m_mappings == null) { 264 m_mappings = new ArrayList<String>(); 265 } 266 m_mappings.add(mapping); 267 } 268 269 /** 270 * @see org.opencms.file.types.I_CmsResourceType#changeLock(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource) 271 */ 272 public void changeLock(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource) 273 throws CmsException { 274 275 securityManager.changeLock(cms.getRequestContext(), resource); 276 } 277 278 /** 279 * @see org.opencms.file.types.I_CmsResourceType#chflags(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, int) 280 */ 281 public void chflags(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, int flags) 282 throws CmsException { 283 284 securityManager.chflags(cms.getRequestContext(), resource, flags); 285 } 286 287 /** 288 * @see org.opencms.file.types.I_CmsResourceType#chtype(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.file.CmsResource, org.opencms.file.types.I_CmsResourceType) 289 */ 290 public void chtype(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, I_CmsResourceType type) 291 throws CmsException { 292 293 // TODO: Refactor driver layer to use resource type id classes (or names) instead of int 294 chtype(cms, securityManager, resource, type.getTypeId()); 295 } 296 297 /** 298 * @see org.opencms.file.types.I_CmsResourceType#chtype(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, int) 299 * 300 * @deprecated 301 * Use {@link #chtype(CmsObject, CmsSecurityManager, CmsResource, I_CmsResourceType)} instead. 302 * Resource types should always be referenced either by its type class (preferred) or by type name. 303 * Use of int based resource type references will be discontinued in a future OpenCms release. 304 */ 305 @Deprecated 306 public void chtype(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, int type) 307 throws CmsException { 308 309 // change type 310 securityManager.chtype(cms.getRequestContext(), resource, type); 311 // type may have changed from non link parseable to link parseable 312 createRelations(cms, securityManager, resource.getRootPath()); 313 } 314 315 /** 316 * @see org.opencms.file.types.I_CmsResourceType#copyResource(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, java.lang.String, CmsResource.CmsResourceCopyMode) 317 */ 318 public void copyResource( 319 CmsObject cms, 320 CmsSecurityManager securityManager, 321 CmsResource source, 322 String destination, 323 CmsResource.CmsResourceCopyMode siblingMode) 324 throws CmsException { 325 326 securityManager.copyResource( 327 cms.getRequestContext(), 328 source, 329 cms.getRequestContext().addSiteRoot(destination), 330 siblingMode); 331 // create the relations for the new resource, this could be improved by an sql query for copying relations 332 createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(destination)); 333 } 334 335 /** 336 * @see org.opencms.file.types.I_CmsResourceType#copyResourceToProject(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource) 337 */ 338 public void copyResourceToProject(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource) 339 throws CmsException { 340 341 securityManager.copyResourceToProject(cms.getRequestContext(), resource); 342 } 343 344 /** 345 * @see org.opencms.file.types.I_CmsResourceType#createResource(org.opencms.file.CmsObject, CmsSecurityManager, java.lang.String, byte[], List) 346 */ 347 public CmsResource createResource( 348 CmsObject cms, 349 CmsSecurityManager securityManager, 350 String resourcename, 351 byte[] content, 352 List<CmsProperty> properties) 353 throws CmsException { 354 355 // initialize a macro resolver with the current user OpenCms context 356 CmsMacroResolver resolver = getMacroResolver(cms, resourcename); 357 358 // add the predefined property values from the XML configuration to the resource 359 List<CmsProperty> newProperties = processDefaultProperties(properties, resolver); 360 361 CmsResource result = securityManager.createResource( 362 cms.getRequestContext(), 363 cms.getRequestContext().addSiteRoot(resourcename), 364 getTypeId(), 365 content, 366 newProperties); 367 368 if ((m_internal != null) && m_internal.booleanValue()) { 369 securityManager.chflags(cms.getRequestContext(), result, result.getFlags() ^ CmsResource.FLAG_INTERNAL); 370 } 371 372 // process the (optional) copy resources from the configuration 373 processCopyResources(cms, resourcename, resolver); 374 375 // create the relations for the new resource 376 createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(resourcename)); 377 378 // return the created resource 379 return result; 380 } 381 382 /** 383 * @see org.opencms.file.types.I_CmsResourceType#createSibling(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, CmsResource, java.lang.String, java.util.List) 384 */ 385 public CmsResource createSibling( 386 CmsObject cms, 387 CmsSecurityManager securityManager, 388 CmsResource source, 389 String destination, 390 List<CmsProperty> properties) 391 throws CmsException { 392 393 CmsResource sibling = securityManager.createSibling( 394 cms.getRequestContext(), 395 source, 396 cms.getRequestContext().addSiteRoot(destination), 397 properties); 398 // create the relations for the new resource, this could be improved by an sql query for copying relations 399 createRelations(cms, securityManager, sibling.getRootPath()); 400 return sibling; 401 } 402 403 /** 404 * @see org.opencms.file.types.I_CmsResourceType#deleteResource(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, CmsResource.CmsResourceDeleteMode) 405 */ 406 public void deleteResource( 407 CmsObject cms, 408 CmsSecurityManager securityManager, 409 CmsResource resource, 410 CmsResource.CmsResourceDeleteMode siblingMode) 411 throws CmsException { 412 413 securityManager.deleteResource(cms.getRequestContext(), resource, siblingMode); 414 } 415 416 /** 417 * Returns <code>true</code>, if this resource type is equal to the given Object.<p> 418 * 419 * Please note: A resource type is identified by it's id {@link #getTypeId()} and it's name {@link #getTypeName()}. 420 * Two resource types are considered equal, if either their id or their name is equal. 421 * This is to prevent issues in the configuration with multiple occurrences of the same name or id.<p> 422 * 423 * @param obj the Object to compare this resource type with 424 * 425 * @return <code>true</code>, if this resource type is equal to the given Object 426 * 427 * @see #getTypeId() 428 * @see #getTypeName() 429 * @see #isIdentical(I_CmsResourceType) 430 * @see java.lang.Object#equals(java.lang.Object) 431 */ 432 @Override 433 public boolean equals(Object obj) { 434 435 if (obj == this) { 436 return true; 437 } 438 if (obj instanceof I_CmsResourceType) { 439 I_CmsResourceType other = (I_CmsResourceType)obj; 440 if ((getTypeName() != null) && (getTypeName().equals(other.getTypeName()))) { 441 return true; 442 } 443 if (getTypeId() == other.getTypeId()) { 444 return true; 445 } 446 } 447 return false; 448 } 449 450 /** 451 * @see org.opencms.file.types.I_CmsResourceType#getAdjustLinksFolder() 452 */ 453 public String getAdjustLinksFolder() { 454 455 return m_adjustLinksFolder; 456 } 457 458 /** 459 * @see org.opencms.file.types.I_CmsResourceType#getCachePropertyDefault() 460 */ 461 public String getCachePropertyDefault() { 462 463 return null; 464 } 465 466 /** 467 * Returns the configured class name of this resource type.<p> 468 * 469 * @see org.opencms.file.types.I_CmsResourceType#getClassName() 470 */ 471 public String getClassName() { 472 473 return m_className; 474 } 475 476 /** 477 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 478 */ 479 public CmsParameterConfiguration getConfiguration() { 480 481 if (LOG.isDebugEnabled()) { 482 LOG.debug(Messages.get().getBundle().key(Messages.LOG_GET_CONFIGURATION_1, this)); 483 } 484 485 return m_configuration; 486 } 487 488 /** 489 * Returns the (unmodifiable) list of copy resources.<p> 490 * 491 * @return the (unmodifiable) list of copy resources 492 */ 493 public List<CmsConfigurationCopyResource> getConfiguredCopyResources() { 494 495 return m_copyResources; 496 } 497 498 /** 499 * Returns the default properties for this resource type in an unmodifiable List.<p> 500 * 501 * @return the default properties for this resource type in an unmodifiable List 502 */ 503 public List<CmsProperty> getConfiguredDefaultProperties() { 504 505 return m_defaultProperties; 506 } 507 508 /** 509 * @see org.opencms.file.types.I_CmsResourceType#getConfiguredMappings() 510 */ 511 public List<String> getConfiguredMappings() { 512 513 return m_mappings; 514 } 515 516 /** 517 * 518 * @see org.opencms.file.types.I_CmsResourceType#getFormattersForResource(org.opencms.file.CmsObject, org.opencms.file.CmsResource) 519 */ 520 public CmsFormatterConfiguration getFormattersForResource(CmsObject cms, CmsResource res) { 521 522 return CmsFormatterConfiguration.EMPTY_CONFIGURATION; 523 } 524 525 /** 526 * @see org.opencms.file.types.I_CmsResourceType#getGalleryPreviewProvider() 527 */ 528 public String getGalleryPreviewProvider() { 529 530 if (m_galleryPreviewProvider == null) { 531 m_galleryPreviewProvider = getConfiguration().getString(CONFIGURATION_GALLERY_PREVIEW_PROVIDER, null); 532 } 533 return m_galleryPreviewProvider; 534 } 535 536 /** 537 * @see org.opencms.file.types.I_CmsResourceType#getGalleryTypes() 538 */ 539 public List<I_CmsResourceType> getGalleryTypes() { 540 541 if (m_galleryTypes == null) { 542 m_galleryTypes = new ArrayList<I_CmsResourceType>(); 543 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_galleryTypeNames)) { 544 CmsResourceManager rm = OpenCms.getResourceManager(); 545 Iterator<String> iTypeNames = CmsStringUtil.splitAsList( 546 m_galleryTypeNames, 547 CmsProperty.VALUE_LIST_DELIMITER).iterator(); 548 while (iTypeNames.hasNext()) { 549 String typeName = iTypeNames.next(); 550 try { 551 m_galleryTypes.add(rm.getResourceType(typeName)); 552 } catch (CmsLoaderException e) { 553 if (LOG.isWarnEnabled()) { 554 LOG.warn(Messages.get().container(Messages.ERR_COULD_NOT_READ_RESOURCE_TYPE_1, typeName)); 555 } 556 } 557 } 558 } 559 560 } 561 return m_galleryTypes; 562 } 563 564 /** 565 * @see org.opencms.file.types.I_CmsResourceType#getLoaderId() 566 */ 567 public abstract int getLoaderId(); 568 569 /** 570 * @see org.opencms.file.types.I_CmsResourceType#getModuleName() 571 */ 572 public String getModuleName() { 573 574 return m_moduleName; 575 } 576 577 /** 578 * @see org.opencms.file.types.I_CmsResourceType#getTypeId() 579 * 580 * @deprecated 581 * Use this class or {@link #getTypeName()} instead. 582 * Resource types should always be referenced either by its type class (preferred) or by type name. 583 * Use of int based resource type references will be discontinued in a future OpenCms release. 584 */ 585 @Deprecated 586 public int getTypeId() { 587 588 return m_typeId; 589 } 590 591 /** 592 * @see org.opencms.file.types.I_CmsResourceType#getTypeName() 593 */ 594 public String getTypeName() { 595 596 return m_typeName; 597 } 598 599 /** 600 * The hash code implementation uses the type name to generate a hash code.<p> 601 * 602 * @see #getTypeId() 603 * @see java.lang.Object#hashCode() 604 */ 605 @Override 606 public int hashCode() { 607 608 return getTypeName().hashCode(); 609 } 610 611 /** 612 * @see org.opencms.file.types.I_CmsResourceType#importResource(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.report.I_CmsReport, java.lang.String, org.opencms.file.CmsResource, byte[], java.util.List) 613 */ 614 public CmsResource importResource( 615 CmsObject cms, 616 CmsSecurityManager securityManager, 617 I_CmsReport report, 618 String resourcename, 619 CmsResource resource, 620 byte[] content, 621 List<CmsProperty> properties) 622 throws CmsException { 623 624 // this triggers the internal "is touched" state 625 // and prevents the security manager from inserting the current time 626 resource.setDateLastModified(resource.getDateLastModified()); 627 // ensure resource record is updated 628 resource.setState(CmsResource.STATE_NEW); 629 return securityManager.importResource( 630 cms.getRequestContext(), 631 cms.getRequestContext().addSiteRoot(resourcename), 632 resource, 633 content, 634 properties, 635 true); 636 } 637 638 /** 639 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 640 */ 641 public final void initConfiguration() { 642 643 // final since subclasses should NOT implement this, but rather the version with 3 String parameters (see below) 644 if (LOG.isDebugEnabled()) { 645 LOG.debug(Messages.get().getBundle().key(Messages.LOG_INIT_CONFIGURATION_1, this)); 646 } 647 } 648 649 /** 650 * @see org.opencms.file.types.I_CmsResourceType#initConfiguration(java.lang.String, java.lang.String, java.lang.String) 651 */ 652 public void initConfiguration(String name, String id, String className) throws CmsConfigurationException { 653 654 if (LOG.isDebugEnabled()) { 655 LOG.debug(Messages.get().getBundle().key(Messages.LOG_INIT_CONFIGURATION_3, this, name, id)); 656 } 657 658 if (m_frozen) { 659 // configuration already frozen 660 throw new CmsConfigurationException( 661 org.opencms.configuration.Messages.get().container( 662 org.opencms.file.types.Messages.ERR_CONFIG_FROZEN_3, 663 className, 664 getTypeName(), 665 Integer.valueOf(getTypeId()))); 666 } 667 668 // freeze the configuration 669 m_frozen = true; 670 671 // set type name and id (please note that some resource types have a fixed type / id) 672 if (name != null) { 673 m_typeName = name; 674 } 675 if (id != null) { 676 m_typeId = Integer.valueOf(id).intValue(); 677 } 678 if (className != null) { 679 m_className = className; 680 } 681 682 // check type id, type name and class name 683 if ((getTypeName() == null) 684 || (getClassName() == null) 685 || ((getTypeId() < 0) 686 && (!m_typeName.equals(CmsResourceTypeUnknownFile.getStaticTypeName())) 687 && (!m_typeName.equals(CmsResourceTypeUnknownFolder.getStaticTypeName())))) { 688 throw new CmsConfigurationException( 689 Messages.get().container( 690 Messages.ERR_INVALID_RESTYPE_CONFIG_3, 691 className, 692 m_typeName, 693 Integer.valueOf(m_typeId))); 694 } 695 696 m_defaultProperties = Collections.unmodifiableList(m_defaultProperties); 697 m_copyResources = Collections.unmodifiableList(m_copyResources); 698 m_mappings = Collections.unmodifiableList(m_mappings); 699 m_configuration = CmsParameterConfiguration.unmodifiableVersion(m_configuration); 700 } 701 702 /** 703 * @see org.opencms.file.types.I_CmsResourceType#initialize(org.opencms.file.CmsObject) 704 */ 705 public void initialize(CmsObject cms) { 706 707 // most resource type do not require any runtime information 708 if (LOG.isDebugEnabled()) { 709 LOG.debug(Messages.get().getBundle().key(Messages.LOG_INITIALIZE_1, this)); 710 } 711 } 712 713 /** 714 * @see org.opencms.file.types.I_CmsResourceType#isAdditionalModuleResourceType() 715 */ 716 public boolean isAdditionalModuleResourceType() { 717 718 return m_addititionalModuleResourceType; 719 } 720 721 /** 722 * @see org.opencms.file.types.I_CmsResourceType#isDirectEditable() 723 */ 724 public boolean isDirectEditable() { 725 726 return false; 727 } 728 729 /** 730 * @see org.opencms.file.types.I_CmsResourceType#isFolder() 731 */ 732 public boolean isFolder() { 733 734 return false; 735 } 736 737 /** 738 * @see org.opencms.file.types.I_CmsResourceType#isIdentical(org.opencms.file.types.I_CmsResourceType) 739 */ 740 public boolean isIdentical(I_CmsResourceType type) { 741 742 if (type == null) { 743 return false; 744 } 745 746 return (getTypeId() == type.getTypeId()) && (getTypeName().equals(type.getTypeName())); 747 } 748 749 /** 750 * @see org.opencms.file.types.I_CmsResourceType#lockResource(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.file.CmsResource, org.opencms.lock.CmsLockType) 751 */ 752 public void lockResource(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, CmsLockType type) 753 throws CmsException { 754 755 securityManager.lockResource(cms.getRequestContext(), resource, type); 756 } 757 758 /** 759 * @see org.opencms.file.types.I_CmsResourceType#moveResource(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.file.CmsResource, java.lang.String) 760 */ 761 public void moveResource( 762 CmsObject cms, 763 CmsSecurityManager securityManager, 764 CmsResource resource, 765 String destination) 766 throws CmsException, CmsIllegalArgumentException { 767 768 String dest = cms.getRequestContext().addSiteRoot(destination); 769 if (resource.getRootPath().equals(dest)) { 770 // move to target with same name is not allowed 771 throw new CmsVfsException( 772 org.opencms.file.Messages.get().container(org.opencms.file.Messages.ERR_MOVE_SAME_NAME_1, destination)); 773 } 774 // check the destination 775 try { 776 securityManager.readResource(cms.getRequestContext(), dest, CmsResourceFilter.ALL); 777 throw new CmsVfsException( 778 org.opencms.file.Messages.get().container( 779 org.opencms.file.Messages.ERR_OVERWRITE_RESOURCE_2, 780 cms.getRequestContext().removeSiteRoot(resource.getRootPath()), 781 destination)); 782 } catch (CmsVfsResourceNotFoundException e) { 783 // ok 784 } 785 String targetName = CmsResource.getName(destination).replace("/", ""); 786 CmsResource.checkResourceName(targetName); 787 // move 788 securityManager.moveResource(cms.getRequestContext(), resource, dest); 789 } 790 791 /** 792 * @see org.opencms.file.types.I_CmsResourceType#removeResourceFromProject(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.file.CmsResource) 793 */ 794 public void removeResourceFromProject(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource) 795 throws CmsException { 796 797 securityManager.removeResourceFromProject(cms.getRequestContext(), resource); 798 } 799 800 /** 801 * @see org.opencms.file.types.I_CmsResourceType#replaceResource(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, org.opencms.file.CmsResource, org.opencms.file.types.I_CmsResourceType, byte[], java.util.List) 802 */ 803 public void replaceResource( 804 CmsObject cms, 805 CmsSecurityManager securityManager, 806 CmsResource resource, 807 I_CmsResourceType type, 808 byte[] content, 809 List<CmsProperty> properties) 810 throws CmsException { 811 812 // TODO: Refactor driver layer to use resource type id classes (or names) instead of int 813 replaceResource(cms, securityManager, resource, type.getTypeId(), content, properties); 814 } 815 816 /** 817 * @see org.opencms.file.types.I_CmsResourceType#replaceResource(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, int, byte[], List) 818 * 819 * @deprecated 820 * Use {@link #replaceResource(CmsObject, CmsSecurityManager, CmsResource, I_CmsResourceType, byte[], List)} instead. 821 * Resource types should always be referenced either by its type class (preferred) or by type name. 822 * Use of int based resource type references will be discontinued in a future OpenCms release. 823 */ 824 @Deprecated 825 public void replaceResource( 826 CmsObject cms, 827 CmsSecurityManager securityManager, 828 CmsResource resource, 829 int type, 830 byte[] content, 831 List<CmsProperty> properties) 832 throws CmsException { 833 834 securityManager.replaceResource(cms.getRequestContext(), resource, type, content, properties); 835 // type may have changed from non link parseable to link parseable 836 createRelations(cms, securityManager, resource.getRootPath()); 837 } 838 839 /** 840 * @see org.opencms.file.types.I_CmsResourceType#restoreResource(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, int) 841 */ 842 public void restoreResource(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, int version) 843 throws CmsException { 844 845 securityManager.restoreResource(cms.getRequestContext(), resource, version); 846 // type may have changed from non link parseable to link parseable 847 createRelations(cms, securityManager, resource.getRootPath()); 848 } 849 850 /** 851 * @see org.opencms.file.types.I_CmsResourceType#setAdditionalModuleResourceType(boolean) 852 */ 853 public void setAdditionalModuleResourceType(boolean additionalType) { 854 855 m_addititionalModuleResourceType = additionalType; 856 } 857 858 /** 859 * @see org.opencms.file.types.I_CmsResourceType#setAdjustLinksFolder(String) 860 */ 861 public void setAdjustLinksFolder(String adjustLinksFolder) { 862 863 m_adjustLinksFolder = adjustLinksFolder; 864 } 865 866 /** 867 * @see org.opencms.file.types.I_CmsResourceType#setDateExpired(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, long, boolean) 868 */ 869 public void setDateExpired( 870 CmsObject cms, 871 CmsSecurityManager securityManager, 872 CmsResource resource, 873 long dateExpired, 874 boolean recursive) 875 throws CmsException { 876 877 securityManager.setDateExpired(cms.getRequestContext(), resource, dateExpired); 878 } 879 880 /** 881 * @see org.opencms.file.types.I_CmsResourceType#setDateLastModified(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, long, boolean) 882 */ 883 public void setDateLastModified( 884 CmsObject cms, 885 CmsSecurityManager securityManager, 886 CmsResource resource, 887 long dateLastModified, 888 boolean recursive) 889 throws CmsException { 890 891 securityManager.setDateLastModified(cms.getRequestContext(), resource, dateLastModified); 892 } 893 894 /** 895 * @see org.opencms.file.types.I_CmsResourceType#setDateReleased(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, long, boolean) 896 */ 897 public void setDateReleased( 898 CmsObject cms, 899 CmsSecurityManager securityManager, 900 CmsResource resource, 901 long dateReleased, 902 boolean recursive) 903 throws CmsException { 904 905 securityManager.setDateReleased(cms.getRequestContext(), resource, dateReleased); 906 } 907 908 /** 909 * @see org.opencms.file.types.I_CmsResourceType#setModuleName(java.lang.String) 910 */ 911 public void setModuleName(String moduleName) { 912 913 m_moduleName = moduleName; 914 } 915 916 /** 917 * @see java.lang.Object#toString() 918 */ 919 @Override 920 public String toString() { 921 922 StringBuffer output = new StringBuffer(); 923 output.append("[ResourceType] class="); 924 output.append(getClass().getName()); 925 output.append(" name="); 926 output.append(getTypeName()); 927 output.append(" id="); 928 output.append(getTypeId()); 929 output.append(" loaderId="); 930 output.append(getLoaderId()); 931 return output.toString(); 932 } 933 934 /** 935 * @see org.opencms.file.types.I_CmsResourceType#undelete(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, boolean) 936 */ 937 public void undelete(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource, boolean recursive) 938 throws CmsException { 939 940 securityManager.undelete(cms.getRequestContext(), resource); 941 } 942 943 /** 944 * @see org.opencms.file.types.I_CmsResourceType#undoChanges(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource, CmsResource.CmsResourceUndoMode) 945 */ 946 public void undoChanges( 947 CmsObject cms, 948 CmsSecurityManager securityManager, 949 CmsResource resource, 950 CmsResource.CmsResourceUndoMode mode) 951 throws CmsException { 952 953 securityManager.undoChanges(cms.getRequestContext(), resource, mode); 954 updateRelationForUndo(cms, securityManager, resource); 955 } 956 957 /** 958 * @see org.opencms.file.types.I_CmsResourceType#unlockResource(org.opencms.file.CmsObject, CmsSecurityManager, CmsResource) 959 */ 960 public void unlockResource(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource) 961 throws CmsException { 962 963 securityManager.unlockResource(cms.getRequestContext(), resource); 964 } 965 966 /** 967 * @see org.opencms.file.types.I_CmsResourceType#writeFile(org.opencms.file.CmsObject, CmsSecurityManager, CmsFile) 968 */ 969 public CmsFile writeFile(CmsObject cms, CmsSecurityManager securityManager, CmsFile resource) throws CmsException { 970 971 if (resource.isFile()) { 972 CmsFile file = securityManager.writeFile(cms.getRequestContext(), resource); 973 I_CmsResourceType type = getResourceType(file); 974 // update the relations after writing!! 975 List<CmsLink> links = null; 976 if (type instanceof I_CmsLinkParseable) { // this check is needed because of type change 977 // if the new type is link parseable 978 links = ((I_CmsLinkParseable)type).parseLinks(cms, file); 979 } 980 // this has to be always executed, even if not link parseable to remove old links 981 securityManager.updateRelationsForResource(cms.getRequestContext(), file, links); 982 return file; 983 } 984 // folders can never be written like a file 985 throw new CmsVfsException( 986 Messages.get().container(Messages.ERR_WRITE_FILE_IS_FOLDER_1, cms.getSitePath(resource))); 987 } 988 989 /** 990 * @see org.opencms.file.types.I_CmsResourceType#writePropertyObject(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, CmsResource, org.opencms.file.CmsProperty) 991 */ 992 public void writePropertyObject( 993 CmsObject cms, 994 CmsSecurityManager securityManager, 995 CmsResource resource, 996 CmsProperty property) 997 throws CmsException { 998 999 securityManager.writePropertyObject(cms.getRequestContext(), resource, property); 1000 } 1001 1002 /** 1003 * @see org.opencms.file.types.I_CmsResourceType#writePropertyObjects(org.opencms.file.CmsObject, org.opencms.db.CmsSecurityManager, CmsResource, java.util.List) 1004 */ 1005 public void writePropertyObjects( 1006 CmsObject cms, 1007 CmsSecurityManager securityManager, 1008 CmsResource resource, 1009 List<CmsProperty> properties) 1010 throws CmsException { 1011 1012 securityManager.writePropertyObjects(cms.getRequestContext(), resource, properties); 1013 } 1014 1015 /** 1016 * Creates the relation information for the resource with the given resource name.<p> 1017 * 1018 * @param cms the cms context 1019 * @param securityManager the security manager 1020 * @param resourceName the resource name of the resource to update the relations for 1021 * 1022 * @return the fresh read resource 1023 * 1024 * @throws CmsException if something goes wrong 1025 */ 1026 protected CmsResource createRelations(CmsObject cms, CmsSecurityManager securityManager, String resourceName) 1027 throws CmsException { 1028 1029 CmsResource resource = securityManager.readResource( 1030 cms.getRequestContext(), 1031 resourceName, 1032 CmsResourceFilter.ALL); 1033 I_CmsResourceType resourceType = getResourceType(resource); 1034 List<CmsLink> links = null; 1035 if (resourceType instanceof I_CmsLinkParseable) { 1036 I_CmsLinkParseable linkParseable = (I_CmsLinkParseable)resourceType; 1037 links = linkParseable.parseLinks(cms, cms.readFile(resource)); 1038 } 1039 securityManager.updateRelationsForResource(cms.getRequestContext(), resource, links); 1040 return resource; 1041 } 1042 1043 /** 1044 * Gets the actual copy resources to use when creating a resource. 1045 * 1046 * @param cms the CMS context 1047 * @param resourcename the path of the resource to create 1048 * @param resolver the macro resolver to use 1049 * 1050 * @return the copy resources to use 1051 */ 1052 protected List<CmsConfigurationCopyResource> getCopyResources( 1053 CmsObject cms, 1054 String resourcename, 1055 CmsMacroResolver resolver) { 1056 1057 return m_copyResources; 1058 } 1059 1060 /** 1061 * Creates a macro resolver based on the current users OpenCms context and the provided resource name.<p> 1062 * 1063 * @param cms the current OpenCms user context 1064 * @param resourcename the resource name for macros like {@link A_CmsResourceType#MACRO_RESOURCE_FOLDER_PATH} 1065 * 1066 * @return a macro resolver based on the current users OpenCms context and the provided resource name 1067 */ 1068 protected CmsMacroResolver getMacroResolver(CmsObject cms, String resourcename) { 1069 1070 CmsMacroResolver result = CmsMacroResolver.newInstance().setCmsObject(cms); 1071 if (isFolder() && (!CmsResource.isFolder(resourcename))) { 1072 // ensure folder ends with "/" so 1073 resourcename = resourcename.concat("/"); 1074 } 1075 // add special mappings for macros in default properties 1076 result.addMacro(MACRO_RESOURCE_ROOT_PATH, cms.getRequestContext().addSiteRoot(resourcename)); 1077 result.addMacro(MACRO_RESOURCE_SITE_PATH, resourcename); 1078 result.addMacro(MACRO_RESOURCE_FOLDER_PATH, CmsResource.getFolderPath(resourcename)); 1079 result.addMacro(MACRO_RESOURCE_FOLDER_PATH_TOUCH, CmsResource.getFolderPath(resourcename)); 1080 result.addMacro(MACRO_RESOURCE_PARENT_PATH, CmsResource.getParentFolder(resourcename)); 1081 result.addMacro(MACRO_RESOURCE_NAME, CmsResource.getName(resourcename)); 1082 1083 return result; 1084 } 1085 1086 /** 1087 * Convenience method to get the initialized resource type instance for the given resource, 1088 * with a fall back to special "unknown" resource types in case the resource type is not configured.<p> 1089 * 1090 * @param resource the resource to get the type for 1091 * 1092 * @return the initialized resource type instance for the given resource 1093 * 1094 * @see org.opencms.loader.CmsResourceManager#getResourceType(int) 1095 */ 1096 protected I_CmsResourceType getResourceType(CmsResource resource) { 1097 1098 return OpenCms.getResourceManager().getResourceType(resource); 1099 } 1100 1101 /** 1102 * Processes the copy resources of this resource type.<p> 1103 * 1104 * @param cms the current OpenCms user context 1105 * @param resourcename the name of the base resource 1106 * @param resolver the resolver used for resolving target macro names 1107 */ 1108 protected void processCopyResources(CmsObject cms, String resourcename, CmsMacroResolver resolver) { 1109 1110 Map<String, String> copiedResources = new HashMap<String, String>(); 1111 for (CmsConfigurationCopyResource oriCopyResource : getCopyResources(cms, resourcename, resolver)) { 1112 1113 // store original copy target 1114 String oriTarget = oriCopyResource.getTarget(); 1115 String target = oriTarget; 1116 1117 List<CmsConfigurationCopyResource> copyResources = new ArrayList<CmsConfigurationCopyResource>(); 1118 try { 1119 // determine if source definition has a wild card character at the end 1120 if (oriCopyResource.getSource().endsWith("*")) { 1121 // add all sub resources of the specified source folder to the set of resources to copy 1122 String source = oriCopyResource.getSource().substring(0, oriCopyResource.getSource().length() - 1); 1123 List<CmsResource> sources = cms.readResources(source, CmsResourceFilter.IGNORE_EXPIRATION, false); 1124 for (CmsResource sourceRes : sources) { 1125 copyResources.add( 1126 new CmsConfigurationCopyResource( 1127 cms.getSitePath(sourceRes), 1128 oriCopyResource.getTarget(), 1129 oriCopyResource.getTypeString())); 1130 } 1131 copiedResources.put(source, resolver.resolveMacros(target)); 1132 } else { 1133 // just add the single specified source 1134 copyResources.add(oriCopyResource); 1135 } 1136 1137 // loop the calculated resources to copy 1138 for (CmsConfigurationCopyResource copyResource : copyResources) { 1139 1140 target = copyResource.getTarget(); 1141 if (copyResource.isTargetWasNull() 1142 || CmsMacroResolver.isMacro(target, MACRO_RESOURCE_FOLDER_PATH) 1143 || CmsMacroResolver.isMacro(target, MACRO_RESOURCE_FOLDER_PATH_TOUCH)) { 1144 // target is just the resource folder, must add source file name to target 1145 target = target.concat(CmsResource.getName(copyResource.getSource())); 1146 } 1147 // now resolve the macros in the target name 1148 target = resolver.resolveMacros(target); 1149 // now resolve possible relative paths in the target 1150 target = CmsFileUtil.normalizePath(CmsLinkManager.getAbsoluteUri(target, resourcename), '/'); 1151 1152 // copy the resource 1153 cms.copyResource(copyResource.getSource(), target, copyResource.getType()); 1154 copiedResources.put(copyResource.getSource(), target); 1155 if (CmsMacroResolver.isMacro(oriTarget, MACRO_RESOURCE_FOLDER_PATH_TOUCH)) { 1156 // copied resources should be touched in order to be able to do additional stuff 1157 CmsResource res = cms.readResource(target); 1158 if (res.isFile()) { 1159 // single file, just rewrite it 1160 CmsFile file = cms.readFile(res); 1161 cms.writeFile(file); 1162 } else { 1163 // folder, get all sub resources that are files 1164 Iterator<CmsResource> it = cms.readResources( 1165 target, 1166 CmsResourceFilter.DEFAULT_FILES, 1167 true).iterator(); 1168 while (it.hasNext()) { 1169 // rewrite the sub resource 1170 CmsResource subRes = it.next(); 1171 CmsFile file = cms.readFile(subRes); 1172 cms.writeFile(file); 1173 } 1174 } 1175 } 1176 1177 } 1178 } catch (Exception e) { 1179 // CmsIllegalArgumentException as well as CmsException 1180 // log the error and continue with the other copy resources 1181 if (LOG.isDebugEnabled()) { 1182 // log stack trace in debug level only 1183 LOG.debug( 1184 Messages.get().getBundle().key( 1185 Messages.LOG_PROCESS_COPY_RESOURCES_3, 1186 resourcename, 1187 oriCopyResource, 1188 target), 1189 e); 1190 } else { 1191 LOG.error( 1192 Messages.get().getBundle().key( 1193 Messages.LOG_PROCESS_COPY_RESOURCES_3, 1194 resourcename, 1195 oriCopyResource, 1196 target)); 1197 } 1198 } 1199 } 1200 // only adjust links for successfully copied resources and if the feature is enabled 1201 try { 1202 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_adjustLinksFolder) && !copiedResources.isEmpty()) { 1203 String realAdjustFolderPath = resolver.resolveMacros(m_adjustLinksFolder); 1204 cms.adjustLinks(copiedResources, realAdjustFolderPath); 1205 } 1206 } catch (CmsException e) { 1207 LOG.error(e.getLocalizedMessage(), e); 1208 } catch (CmsIllegalArgumentException e) { 1209 LOG.error(e.getLocalizedMessage(), e); 1210 } 1211 } 1212 1213 /** 1214 * Returns a list of property objects that are attached to the resource on creation.<p> 1215 * 1216 * It's possible to use OpenCms macros for the property values. 1217 * Please see {@link CmsMacroResolver} for allowed macro values.<p> 1218 * 1219 * @param properties the (optional) properties provided by the user 1220 * @param resolver the resolver used to resolve the macro values 1221 * 1222 * @return a list of property objects that are attached to the resource on creation 1223 */ 1224 protected List<CmsProperty> processDefaultProperties(List<CmsProperty> properties, CmsMacroResolver resolver) { 1225 1226 if ((m_defaultProperties == null) || (m_defaultProperties.size() == 0)) { 1227 // no default properties are defined 1228 return properties; 1229 } 1230 1231 // the properties must be copied since the macros could contain macros that are 1232 // resolved differently for every user / context 1233 ArrayList<CmsProperty> result = new ArrayList<CmsProperty>(); 1234 Iterator<CmsProperty> i = m_defaultProperties.iterator(); 1235 1236 while (i.hasNext()) { 1237 // create a clone of the next property 1238 CmsProperty property = (i.next()).clone(); 1239 1240 // resolve possible macros in the property values 1241 if (property.getResourceValue() != null) { 1242 property.setResourceValue(resolver.resolveMacros(property.getResourceValue())); 1243 } 1244 if (property.getStructureValue() != null) { 1245 property.setStructureValue(resolver.resolveMacros(property.getStructureValue())); 1246 } 1247 1248 // save the new property in the result list 1249 result.add(property); 1250 } 1251 1252 // add the original properties 1253 if (properties != null) { 1254 result.addAll(properties); 1255 } 1256 1257 // return the result 1258 return result; 1259 } 1260 1261 /** 1262 * Update the relations after an undo changes operation.<p> 1263 * 1264 * @param cms the cms context 1265 * @param securityManager the security manager 1266 * @param resource the resource that has been undone 1267 * 1268 * @throws CmsException if something goes wrong 1269 */ 1270 protected void updateRelationForUndo(CmsObject cms, CmsSecurityManager securityManager, CmsResource resource) 1271 throws CmsException { 1272 1273 // type may have changed from non link parseable to link parseable 1274 CmsResource undoneResource1 = null; 1275 try { 1276 // first try to locate the resource by path 1277 undoneResource1 = createRelations(cms, securityManager, resource.getRootPath()); 1278 } catch (CmsVfsResourceNotFoundException e) { 1279 // ignore, undone move operation 1280 } 1281 // now, in case a move operation has been undone, locate the resource by id 1282 CmsResource undoneResource2 = securityManager.readResource( 1283 cms.getRequestContext(), 1284 resource.getStructureId(), 1285 CmsResourceFilter.ALL); 1286 if (!undoneResource2.equals(undoneResource1)) { 1287 I_CmsResourceType resourceType = getResourceType(resource); 1288 List<CmsLink> links = null; 1289 if (resourceType instanceof I_CmsLinkParseable) { 1290 I_CmsLinkParseable linkParseable = (I_CmsLinkParseable)resourceType; 1291 if ((undoneResource1 == null) || !undoneResource2.getRootPath().equals(undoneResource1.getRootPath())) { 1292 try { 1293 links = linkParseable.parseLinks(cms, cms.readFile(undoneResource2)); 1294 } catch (CmsException e) { 1295 if (LOG.isWarnEnabled()) { 1296 LOG.warn(e.getLocalizedMessage(), e); 1297 } 1298 } catch (CmsRuntimeException e) { 1299 if (LOG.isWarnEnabled()) { 1300 LOG.warn(e.getLocalizedMessage(), e); 1301 } 1302 } 1303 } 1304 } 1305 securityManager.updateRelationsForResource(cms.getRequestContext(), undoneResource2, links); 1306 } 1307 } 1308}