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.loader; 029 030import org.opencms.cache.CmsVfsMemoryObjectCache; 031import org.opencms.configuration.CmsConfigurationException; 032import org.opencms.configuration.CmsVfsConfiguration; 033import org.opencms.file.CmsObject; 034import org.opencms.file.CmsProperty; 035import org.opencms.file.CmsPropertyDefinition; 036import org.opencms.file.CmsResource; 037import org.opencms.file.CmsResourceFilter; 038import org.opencms.file.collectors.I_CmsResourceCollector; 039import org.opencms.file.types.CmsResourceTypeBinary; 040import org.opencms.file.types.CmsResourceTypeFolder; 041import org.opencms.file.types.CmsResourceTypePlain; 042import org.opencms.file.types.CmsResourceTypeUnknownFile; 043import org.opencms.file.types.CmsResourceTypeUnknownFolder; 044import org.opencms.file.types.CmsResourceTypeXmlContent; 045import org.opencms.file.types.I_CmsResourceType; 046import org.opencms.main.CmsException; 047import org.opencms.main.CmsLog; 048import org.opencms.main.OpenCms; 049import org.opencms.module.CmsModule; 050import org.opencms.module.CmsModuleManager; 051import org.opencms.relations.CmsRelationType; 052import org.opencms.security.CmsRole; 053import org.opencms.security.CmsRoleViolationException; 054import org.opencms.util.CmsDefaultSet; 055import org.opencms.util.CmsHtmlConverter; 056import org.opencms.util.CmsHtmlConverterJTidy; 057import org.opencms.util.CmsHtmlConverterOption; 058import org.opencms.util.CmsResourceTranslator; 059import org.opencms.util.CmsStringUtil; 060import org.opencms.util.I_CmsHtmlConverter; 061import org.opencms.workplace.CmsWorkplace; 062import org.opencms.xml.CmsXmlContentDefinition; 063 064import java.io.IOException; 065import java.util.ArrayList; 066import java.util.Collections; 067import java.util.HashMap; 068import java.util.Iterator; 069import java.util.List; 070import java.util.Locale; 071import java.util.Map; 072import java.util.Properties; 073 074import javax.servlet.ServletException; 075import javax.servlet.http.HttpServletRequest; 076import javax.servlet.http.HttpServletResponse; 077 078import org.apache.commons.logging.Log; 079 080/** 081 * Collects all available resource loaders, resource types and resource collectors at startup and provides 082 * methods to access them during OpenCms runtime.<p> 083 * 084 * @since 6.0.0 085 */ 086public class CmsResourceManager { 087 088 /** 089 * Bean containing a template resource and the name of the template.<p> 090 */ 091 public static class NamedTemplate { 092 093 /** The template name. */ 094 private String m_name; 095 096 /** The template resource. */ 097 private CmsResource m_resource; 098 099 /** 100 * Creates a new instance.<p> 101 * 102 * @param resource the template resource 103 * @param name the template name 104 */ 105 public NamedTemplate(CmsResource resource, String name) { 106 107 m_resource = resource; 108 m_name = name; 109 } 110 111 /** 112 * Gets the template name.<p> 113 * 114 * @return the template name 115 */ 116 public String getName() { 117 118 return m_name; 119 } 120 121 /** 122 * Gets the template resource.<p> 123 * 124 * @return the template resource 125 */ 126 public CmsResource getResource() { 127 128 return m_resource; 129 } 130 } 131 132 /** 133 * Contains the part of the resource manager configuration that can be changed 134 * during runtime by the import / deletion of a module.<p> 135 * 136 * A module can add resource types and extension mappings to resource types.<p> 137 */ 138 static final class CmsResourceManagerConfiguration { 139 140 /** The mappings of file extensions to resource types. */ 141 protected Map<String, String> m_extensionMappings; 142 143 /** A list that contains all initialized resource types. */ 144 protected List<I_CmsResourceType> m_resourceTypeList; 145 146 /** A list that contains all initialized resource types, plus configured types for "unknown" resources. */ 147 protected List<I_CmsResourceType> m_resourceTypeListWithUnknown; 148 149 /** A map that contains all initialized resource types mapped to their type id. */ 150 private Map<Integer, I_CmsResourceType> m_resourceTypeIdMap; 151 152 /** A map that contains all initialized resource types mapped to their type name. */ 153 private Map<String, I_CmsResourceType> m_resourceTypeNameMap; 154 155 /** 156 * Creates a new resource manager data storage.<p> 157 */ 158 protected CmsResourceManagerConfiguration() { 159 160 m_resourceTypeIdMap = new HashMap<Integer, I_CmsResourceType>(128); 161 m_resourceTypeNameMap = new HashMap<String, I_CmsResourceType>(128); 162 m_extensionMappings = new HashMap<String, String>(128); 163 m_resourceTypeList = new ArrayList<I_CmsResourceType>(32); 164 } 165 166 /** 167 * Adds a resource type to the list of configured resource types.<p> 168 * 169 * @param type the resource type to add 170 */ 171 protected void addResourceType(I_CmsResourceType type) { 172 173 m_resourceTypeIdMap.put(Integer.valueOf(type.getTypeId()), type); 174 m_resourceTypeNameMap.put(type.getTypeName(), type); 175 m_resourceTypeList.add(type); 176 } 177 178 /** 179 * Freezes the current configuration by making all data structures unmodifiable 180 * that can be accessed form outside this class.<p> 181 * 182 * @param restypeUnknownFolder the configured default resource type for unknown folders 183 * @param restypeUnknownFile the configured default resource type for unknown files 184 */ 185 protected void freeze(I_CmsResourceType restypeUnknownFolder, I_CmsResourceType restypeUnknownFile) { 186 187 // generate the resource type list with unknown resource types 188 m_resourceTypeListWithUnknown = new ArrayList<I_CmsResourceType>(m_resourceTypeList.size() + 2); 189 if (restypeUnknownFolder != null) { 190 m_resourceTypeListWithUnknown.add(restypeUnknownFolder); 191 } 192 if (restypeUnknownFile != null) { 193 m_resourceTypeListWithUnknown.add(restypeUnknownFile); 194 } 195 m_resourceTypeListWithUnknown.addAll(m_resourceTypeList); 196 197 // freeze the current configuration 198 m_resourceTypeListWithUnknown = Collections.unmodifiableList(m_resourceTypeListWithUnknown); 199 m_resourceTypeList = Collections.unmodifiableList(m_resourceTypeList); 200 m_extensionMappings = Collections.unmodifiableMap(m_extensionMappings); 201 } 202 203 /** 204 * Returns the configured resource type with the matching type id, or <code>null</code> 205 * if a resource type with that id is not configured.<p> 206 * 207 * @param typeId the type id to get the resource type for 208 * 209 * @return the configured resource type with the matching type id, or <code>null</code> 210 */ 211 protected I_CmsResourceType getResourceTypeById(int typeId) { 212 213 return m_resourceTypeIdMap.get(Integer.valueOf(typeId)); 214 } 215 216 /** 217 * Returns the configured resource type with the matching type name, or <code>null</code> 218 * if a resource type with that name is not configured.<p> 219 * 220 * @param typeName the type name to get the resource type for 221 * 222 * @return the configured resource type with the matching type name, or <code>null</code> 223 */ 224 protected I_CmsResourceType getResourceTypeByName(String typeName) { 225 226 return m_resourceTypeNameMap.get(typeName); 227 } 228 } 229 230 /** The path to the default template. */ 231 public static final String DEFAULT_TEMPLATE = CmsWorkplace.VFS_PATH_COMMONS + "template/default.jsp"; 232 233 /** The MIME type <code>"text/html"</code>. */ 234 public static final String MIMETYPE_HTML = "text/html"; 235 236 /** The MIME type <code>"text/plain"</code>. */ 237 public static final String MIMETYPE_TEXT = "text/plain"; 238 239 /** The log object for this class. */ 240 private static final Log LOG = CmsLog.getLog(CmsResourceManager.class); 241 242 /** The map for all configured collector names, mapped to their collector class. */ 243 private Map<String, I_CmsResourceCollector> m_collectorNameMappings; 244 245 /** The list of all currently configured content collector instances. */ 246 private List<I_CmsResourceCollector> m_collectors; 247 248 /** The current resource manager configuration. */ 249 private CmsResourceManagerConfiguration m_configuration; 250 251 /** The list of all configured HTML converters. */ 252 private List<CmsHtmlConverterOption> m_configuredHtmlConverters; 253 254 /** The list of all configured MIME types. */ 255 private List<CmsMimeType> m_configuredMimeTypes; 256 257 /** The list of all configured relation types. */ 258 private List<CmsRelationType> m_configuredRelationTypes; 259 260 /** Filename translator, used only for the creation of new files. */ 261 private CmsResourceTranslator m_fileTranslator; 262 263 /** Folder translator, used to translate all accesses to resources. */ 264 private CmsResourceTranslator m_folderTranslator; 265 266 /** Indicates if the configuration is finalized (frozen). */ 267 private boolean m_frozen; 268 269 /** The OpenCms map of configured HTML converters. */ 270 private Map<String, String> m_htmlConverters; 271 272 /** A list that contains all initialized resource loaders. */ 273 private List<I_CmsResourceLoader> m_loaderList; 274 275 /** All initialized resource loaders, mapped to their id. */ 276 private I_CmsResourceLoader[] m_loaders; 277 278 /** The OpenCms map of configured MIME types. */ 279 private Map<String, String> m_mimeTypes; 280 281 /** The URL name generator for XML contents. */ 282 private I_CmsFileNameGenerator m_nameGenerator = new CmsDefaultFileNameGenerator(); 283 284 /** A list that contains all resource types added from the XML configuration. */ 285 private List<I_CmsResourceType> m_resourceTypesFromXml; 286 287 /** The configured default type for files when the resource type is missing. */ 288 private I_CmsResourceType m_restypeUnknownFile; 289 290 /** The configured default type for folders when the resource type is missing. */ 291 private I_CmsResourceType m_restypeUnknownFolder; 292 293 /** Cache for template names. */ 294 private CmsVfsMemoryObjectCache m_templateNameCache = new CmsVfsMemoryObjectCache(); 295 296 /** XSD translator, used to translate all accesses to XML schemas from Strings. */ 297 private CmsResourceTranslator m_xsdTranslator; 298 299 /** 300 * Creates a new instance for the resource manager, 301 * will be called by the VFS configuration manager.<p> 302 */ 303 public CmsResourceManager() { 304 305 if (CmsLog.INIT.isInfoEnabled()) { 306 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_STARTING_LOADER_CONFIG_0)); 307 } 308 309 m_resourceTypesFromXml = new ArrayList<I_CmsResourceType>(); 310 m_loaders = new I_CmsResourceLoader[16]; 311 m_loaderList = new ArrayList<I_CmsResourceLoader>(); 312 m_configuredMimeTypes = new ArrayList<CmsMimeType>(); 313 m_configuredRelationTypes = new ArrayList<CmsRelationType>(); 314 m_configuredHtmlConverters = new ArrayList<CmsHtmlConverterOption>(); 315 } 316 317 /** 318 * Adds a given content collector class to the type manager.<p> 319 * 320 * @param className the name of the class to add 321 * @param order the order number for this collector 322 * 323 * @return the created content collector instance 324 * 325 * @throws CmsConfigurationException in case the collector could not be properly initialized 326 */ 327 public synchronized I_CmsResourceCollector addContentCollector(String className, String order) 328 throws CmsConfigurationException { 329 330 Class<?> classClazz; 331 // init class for content collector 332 try { 333 classClazz = Class.forName(className); 334 } catch (ClassNotFoundException e) { 335 LOG.error(Messages.get().getBundle().key(Messages.LOG_CONTENT_COLLECTOR_CLASS_NOT_FOUND_1, className), e); 336 return null; 337 } 338 339 I_CmsResourceCollector collector; 340 try { 341 collector = (I_CmsResourceCollector)classClazz.newInstance(); 342 } catch (InstantiationException e) { 343 throw new CmsConfigurationException( 344 Messages.get().container(Messages.ERR_INVALID_COLLECTOR_NAME_1, className)); 345 } catch (IllegalAccessException e) { 346 throw new CmsConfigurationException( 347 Messages.get().container(Messages.ERR_INVALID_COLLECTOR_NAME_1, className)); 348 } catch (ClassCastException e) { 349 throw new CmsConfigurationException( 350 Messages.get().container(Messages.ERR_INVALID_COLLECTOR_NAME_1, className)); 351 } 352 353 // set the configured order for the collector 354 int ord = 0; 355 try { 356 ord = Integer.valueOf(order).intValue(); 357 } catch (NumberFormatException e) { 358 LOG.error(Messages.get().getBundle().key(Messages.LOG_COLLECTOR_BAD_ORDER_NUMBER_1, className), e); 359 } 360 collector.setOrder(ord); 361 362 if (CmsLog.INIT.isInfoEnabled()) { 363 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ADD_COLLECTOR_CLASS_2, className, order)); 364 } 365 366 // extend or init the current list of configured collectors 367 if (m_collectors != null) { 368 m_collectors = new ArrayList<I_CmsResourceCollector>(m_collectors); 369 m_collectorNameMappings = new HashMap<String, I_CmsResourceCollector>(m_collectorNameMappings); 370 } else { 371 m_collectors = new ArrayList<I_CmsResourceCollector>(); 372 m_collectorNameMappings = new HashMap<String, I_CmsResourceCollector>(); 373 } 374 375 if (!m_collectors.contains(collector)) { 376 // this is a collector not currently configured 377 m_collectors.add(collector); 378 379 Iterator<String> i = collector.getCollectorNames().iterator(); 380 while (i.hasNext()) { 381 String name = i.next(); 382 if (m_collectorNameMappings.containsKey(name)) { 383 // this name is already configured, check the order of the collector 384 I_CmsResourceCollector otherCollector = m_collectorNameMappings.get(name); 385 if (collector.getOrder() > otherCollector.getOrder()) { 386 // new collector has a greater order than the old collector in the Map 387 m_collectorNameMappings.put(name, collector); 388 if (CmsLog.INIT.isInfoEnabled()) { 389 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_COLLECTOR_REPLACED_1, name)); 390 } 391 } else { 392 if (CmsLog.INIT.isInfoEnabled()) { 393 CmsLog.INIT.info( 394 Messages.get().getBundle().key(Messages.INIT_DUPLICATE_COLLECTOR_SKIPPED_1, name)); 395 } 396 } 397 } else { 398 m_collectorNameMappings.put(name, collector); 399 if (CmsLog.INIT.isInfoEnabled()) { 400 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ADD_COLLECTOR_1, name)); 401 } 402 } 403 } 404 } 405 406 // ensure list is unmodifiable to avoid potential misuse or accidental changes 407 Collections.sort(m_collectors); 408 m_collectors = Collections.unmodifiableList(m_collectors); 409 m_collectorNameMappings = Collections.unmodifiableMap(m_collectorNameMappings); 410 411 // return the created collector instance 412 return collector; 413 } 414 415 /** 416 * Adds a new HTML converter class to internal list of loaded converter classes.<p> 417 * 418 * @param name the name of the option that should trigger the HTML converter class 419 * @param className the name of the class to add 420 * 421 * @return the created HTML converter instance 422 * 423 * @throws CmsConfigurationException in case the HTML converter could not be properly initialized 424 */ 425 public I_CmsHtmlConverter addHtmlConverter(String name, String className) throws CmsConfigurationException { 426 427 // check if new conversion option can still be added 428 if (m_frozen) { 429 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 430 } 431 432 Class<?> classClazz; 433 // init class for content converter 434 try { 435 classClazz = Class.forName(className); 436 } catch (ClassNotFoundException e) { 437 LOG.error(Messages.get().getBundle().key(Messages.LOG_HTML_CONVERTER_CLASS_NOT_FOUND_1, className), e); 438 return null; 439 } 440 441 I_CmsHtmlConverter converter; 442 try { 443 converter = (I_CmsHtmlConverter)classClazz.newInstance(); 444 } catch (InstantiationException e) { 445 throw new CmsConfigurationException( 446 Messages.get().container(Messages.ERR_INVALID_HTMLCONVERTER_NAME_1, className)); 447 } catch (IllegalAccessException e) { 448 throw new CmsConfigurationException( 449 Messages.get().container(Messages.ERR_INVALID_HTMLCONVERTER_NAME_1, className)); 450 } catch (ClassCastException e) { 451 throw new CmsConfigurationException( 452 Messages.get().container(Messages.ERR_INVALID_HTMLCONVERTER_NAME_1, className)); 453 } 454 455 if (CmsLog.INIT.isInfoEnabled()) { 456 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ADD_HTML_CONVERTER_CLASS_2, className, name)); 457 } 458 459 m_configuredHtmlConverters.add(new CmsHtmlConverterOption(name, className)); 460 return converter; 461 } 462 463 /** 464 * Adds a new loader to the internal list of loaded loaders.<p> 465 * 466 * @param loader the loader to add 467 * @throws CmsConfigurationException in case the resource manager configuration is already initialized 468 */ 469 public void addLoader(I_CmsResourceLoader loader) throws CmsConfigurationException { 470 471 // check if new loaders can still be added 472 if (m_frozen) { 473 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 474 } 475 476 // add the loader to the internal list of loaders 477 int pos = loader.getLoaderId(); 478 if (pos >= m_loaders.length) { 479 I_CmsResourceLoader[] buffer = new I_CmsResourceLoader[pos * 2]; 480 System.arraycopy(m_loaders, 0, buffer, 0, m_loaders.length); 481 m_loaders = buffer; 482 } 483 m_loaders[pos] = loader; 484 m_loaderList.add(loader); 485 if (CmsLog.INIT.isInfoEnabled()) { 486 CmsLog.INIT.info( 487 Messages.get().getBundle().key( 488 Messages.INIT_ADD_LOADER_2, 489 loader.getClass().getName(), 490 new Integer(pos))); 491 } 492 } 493 494 /** 495 * Adds a new MIME type from the XML configuration to the internal list of MIME types.<p> 496 * 497 * @param extension the MIME type extension 498 * @param type the MIME type description 499 * 500 * @return the created MIME type instance 501 * 502 * @throws CmsConfigurationException in case the resource manager configuration is already initialized 503 */ 504 public CmsMimeType addMimeType(String extension, String type) throws CmsConfigurationException { 505 506 // check if new mime types can still be added 507 if (m_frozen) { 508 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 509 } 510 511 CmsMimeType mimeType = new CmsMimeType(extension, type); 512 m_configuredMimeTypes.add(mimeType); 513 return mimeType; 514 } 515 516 /** 517 * Adds a new relation type from the XML configuration to the list of user defined relation types.<p> 518 * 519 * @param name the name of the relation type 520 * @param type the type of the relation type, weak or strong 521 * 522 * @return the new created relation type instance 523 * 524 * @throws CmsConfigurationException in case the resource manager configuration is already initialized 525 */ 526 public CmsRelationType addRelationType(String name, String type) throws CmsConfigurationException { 527 528 // check if new relation types can still be added 529 if (m_frozen) { 530 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 531 } 532 533 CmsRelationType relationType = new CmsRelationType(m_configuredRelationTypes.size(), name, type); 534 m_configuredRelationTypes.add(relationType); 535 return relationType; 536 } 537 538 /** 539 * Adds a new resource type from the XML configuration to the internal list of loaded resource types.<p> 540 * 541 * Resource types can also be added from a module.<p> 542 * 543 * @param resourceType the resource type to add 544 * @throws CmsConfigurationException in case the resource manager configuration is already initialized 545 */ 546 public void addResourceType(I_CmsResourceType resourceType) throws CmsConfigurationException { 547 548 // check if new resource types can still be added 549 if (m_frozen) { 550 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 551 } 552 553 I_CmsResourceType conflictingType = null; 554 if (resourceType.getTypeId() == CmsResourceTypeUnknownFile.RESOURCE_TYPE_ID) { 555 // default unknown file resource type 556 if (m_restypeUnknownFile != null) { 557 // error: already set 558 conflictingType = m_restypeUnknownFile; 559 } else { 560 m_restypeUnknownFile = resourceType; 561 return; 562 } 563 } else if (resourceType.getTypeId() == CmsResourceTypeUnknownFolder.RESOURCE_TYPE_ID) { 564 // default unknown folder resource type 565 if (m_restypeUnknownFolder != null) { 566 // error: already set 567 conflictingType = m_restypeUnknownFolder; 568 } else { 569 m_restypeUnknownFolder = resourceType; 570 return; 571 } 572 } else { 573 // normal resource types 574 int conflictIndex = m_resourceTypesFromXml.indexOf(resourceType); 575 if (conflictIndex >= 0) { 576 conflictingType = m_resourceTypesFromXml.get(conflictIndex); 577 } 578 } 579 if (conflictingType != null) { 580 // configuration problem: the resource type (or at least the id or the name) is already configured 581 throw new CmsConfigurationException( 582 Messages.get().container( 583 Messages.ERR_CONFLICTING_RESOURCE_TYPES_4, 584 new Object[] { 585 resourceType.getTypeName(), 586 new Integer(resourceType.getTypeId()), 587 conflictingType.getTypeName(), 588 new Integer(conflictingType.getTypeId())})); 589 } 590 591 m_resourceTypesFromXml.add(resourceType); 592 } 593 594 /** 595 * Gets the map of forbidden contexts for resource types.<p> 596 * 597 * @param cms the current CMS context 598 * @return the map from resource types to the forbidden contexts 599 */ 600 public Map<String, CmsDefaultSet<String>> getAllowedContextMap(CmsObject cms) { 601 602 Map<String, CmsDefaultSet<String>> result = new HashMap<String, CmsDefaultSet<String>>(); 603 for (I_CmsResourceType resType : getResourceTypes()) { 604 if (resType instanceof CmsResourceTypeXmlContent) { 605 String schema = null; 606 try { 607 schema = ((CmsResourceTypeXmlContent)resType).getSchema(); 608 if (schema != null) { 609 CmsXmlContentDefinition contentDefinition = CmsXmlContentDefinition.unmarshal(cms, schema); 610 611 CmsDefaultSet<String> allowedContexts = contentDefinition.getContentHandler().getAllowedTemplates(); 612 result.put(resType.getTypeName(), allowedContexts); 613 } else { 614 LOG.info( 615 "No schema for XML type " + resType.getTypeName() + " / " + resType.getClass().getName()); 616 } 617 } catch (Exception e) { 618 LOG.error( 619 "Error in getAllowedContextMap, schema=" 620 + schema 621 + ", type=" 622 + resType.getTypeName() 623 + ", " 624 + e.getLocalizedMessage(), 625 e); 626 } 627 } 628 } 629 return result; 630 } 631 632 /** 633 * Returns the configured content collector with the given name, or <code>null</code> if 634 * no collector with this name is configured.<p> 635 * 636 * @param collectorName the name of the collector to get 637 * @return the configured content collector with the given name 638 */ 639 public I_CmsResourceCollector getContentCollector(String collectorName) { 640 641 return m_collectorNameMappings.get(collectorName); 642 } 643 644 /** 645 * Returns the default resource type for the given resource name, using the 646 * configured resource type file extensions.<p> 647 * 648 * In case the given name does not map to a configured resource type, 649 * {@link CmsResourceTypePlain} is returned.<p> 650 * 651 * This is only required (and should <i>not</i> be used otherwise) when 652 * creating a new resource automatically during file upload or synchronization. 653 * Only in this case, the file type for the new resource is determined using this method. 654 * Otherwise the resource type is <i>always</i> stored as part of the resource, 655 * and is <i>not</i> related to the file name.<p> 656 * 657 * @param resourcename the resource name to look up the resource type for 658 * 659 * @return the default resource type for the given resource name 660 * 661 * @throws CmsException if something goes wrong 662 */ 663 public I_CmsResourceType getDefaultTypeForName(String resourcename) throws CmsException { 664 665 String typeName = null; 666 String suffix = null; 667 if (CmsStringUtil.isNotEmpty(resourcename)) { 668 int pos = resourcename.lastIndexOf('.'); 669 if (pos >= 0) { 670 suffix = resourcename.substring(pos); 671 if (CmsStringUtil.isNotEmpty(suffix)) { 672 suffix = suffix.toLowerCase(); 673 typeName = m_configuration.m_extensionMappings.get(suffix); 674 675 } 676 } 677 } 678 679 if (typeName == null) { 680 // use default type "plain" 681 typeName = CmsResourceTypePlain.getStaticTypeName(); 682 } 683 684 if (CmsLog.INIT.isDebugEnabled()) { 685 CmsLog.INIT.debug(Messages.get().getBundle().key(Messages.INIT_GET_RESTYPE_2, typeName, suffix)); 686 } 687 // look up and return the resource type 688 return getResourceType(typeName); 689 } 690 691 /** 692 * Returns the file extensions (suffixes) mappings to resource types.<p> 693 * 694 * @return a Map with all known file extensions as keys and their resource types as values. 695 */ 696 public Map<String, String> getExtensionMapping() { 697 698 return m_configuration.m_extensionMappings; 699 } 700 701 /** 702 * Returns the file translator.<p> 703 * 704 * @return the file translator 705 */ 706 public CmsResourceTranslator getFileTranslator() { 707 708 return m_fileTranslator; 709 } 710 711 /** 712 * Returns the folder translator.<p> 713 * 714 * @return the folder translator 715 */ 716 public CmsResourceTranslator getFolderTranslator() { 717 718 return m_folderTranslator; 719 } 720 721 /** 722 * Returns the matching HTML converter class name for the specified option name.<p> 723 * 724 * @param name the name of the option that should trigger the HTML converter class 725 * 726 * @return the matching HTML converter class name for the specified option name or <code>null</code> if no match is found 727 */ 728 public String getHtmlConverter(String name) { 729 730 return m_htmlConverters.get(name); 731 } 732 733 /** 734 * Returns an unmodifiable List of the configured {@link CmsHtmlConverterOption} objects.<p> 735 * 736 * @return an unmodifiable List of the configured {@link CmsHtmlConverterOption} objects 737 */ 738 public List<CmsHtmlConverterOption> getHtmlConverters() { 739 740 return m_configuredHtmlConverters; 741 } 742 743 /** 744 * Returns the loader class instance for a given resource.<p> 745 * 746 * @param resource the resource 747 * @return the appropriate loader class instance 748 * @throws CmsLoaderException if something goes wrong 749 */ 750 public I_CmsResourceLoader getLoader(CmsResource resource) throws CmsLoaderException { 751 752 return getLoader(getResourceType(resource.getTypeId()).getLoaderId()); 753 } 754 755 /** 756 * Returns the loader class instance for the given loader id.<p> 757 * 758 * @param id the id of the loader to return 759 * @return the loader class instance for the given loader id 760 */ 761 public I_CmsResourceLoader getLoader(int id) { 762 763 return m_loaders[id]; 764 } 765 766 /** 767 * Returns the (unmodifiable array) list with all initialized resource loaders.<p> 768 * 769 * @return the (unmodifiable array) list with all initialized resource loaders 770 */ 771 public List<I_CmsResourceLoader> getLoaders() { 772 773 return m_loaderList; 774 } 775 776 /** 777 * Returns the MIME type for a specified file name.<p> 778 * 779 * If an encoding parameter that is not <code>null</code> is provided, 780 * the returned MIME type is extended with a <code>; charset={encoding}</code> setting.<p> 781 * 782 * If no MIME type for the given filename can be determined, the 783 * default <code>{@link #MIMETYPE_HTML}</code> is used.<p> 784 * 785 * @param filename the file name to check the MIME type for 786 * @param encoding the default encoding (charset) in case of MIME types is of type "text" 787 * 788 * @return the MIME type for a specified file 789 */ 790 public String getMimeType(String filename, String encoding) { 791 792 return getMimeType(filename, encoding, MIMETYPE_HTML); 793 } 794 795 /** 796 * Returns the MIME type for a specified file name.<p> 797 * 798 * If an encoding parameter that is not <code>null</code> is provided, 799 * the returned MIME type is extended with a <code>; charset={encoding}</code> setting.<p> 800 * 801 * If no MIME type for the given filename can be determined, the 802 * provided default is used.<p> 803 * 804 * @param filename the file name to check the MIME type for 805 * @param encoding the default encoding (charset) in case of MIME types is of type "text" 806 * @param defaultMimeType the default MIME type to use if no matching type for the filename is found 807 * 808 * @return the MIME type for a specified file 809 */ 810 public String getMimeType(String filename, String encoding, String defaultMimeType) { 811 812 String mimeType = null; 813 int lastDot = filename.lastIndexOf('.'); 814 // check the MIME type for the file extension 815 if ((lastDot > 0) && (lastDot < (filename.length() - 1))) { 816 mimeType = m_mimeTypes.get(filename.substring(lastDot).toLowerCase(Locale.ENGLISH)); 817 } 818 if (mimeType == null) { 819 mimeType = defaultMimeType; 820 if (mimeType == null) { 821 // no default MIME type was provided 822 return null; 823 } 824 } 825 StringBuffer result = new StringBuffer(mimeType); 826 if ((encoding != null) 827 && (mimeType.startsWith("text") || mimeType.endsWith("javascript")) 828 && (mimeType.indexOf("charset") == -1)) { 829 result.append("; charset="); 830 result.append(encoding); 831 } 832 return result.toString(); 833 } 834 835 /** 836 * Returns an unmodifiable List of the configured {@link CmsMimeType} objects.<p> 837 * 838 * @return an unmodifiable List of the configured {@link CmsMimeType} objects 839 */ 840 public List<CmsMimeType> getMimeTypes() { 841 842 return m_configuredMimeTypes; 843 } 844 845 /** 846 * Returns the name generator for XML content file names.<p> 847 * 848 * @return the name generator for XML content file names. 849 */ 850 public I_CmsFileNameGenerator getNameGenerator() { 851 852 if (m_nameGenerator == null) { 853 m_nameGenerator = new CmsDefaultFileNameGenerator(); 854 } 855 return m_nameGenerator; 856 } 857 858 /** 859 * Returns an (unmodifiable) list of class names of all currently registered content collectors 860 * ({@link I_CmsResourceCollector} objects).<p> 861 * 862 * @return an (unmodifiable) list of class names of all currently registered content collectors 863 * ({@link I_CmsResourceCollector} objects) 864 */ 865 public List<I_CmsResourceCollector> getRegisteredContentCollectors() { 866 867 return m_collectors; 868 } 869 870 /** 871 * Returns an unmodifiable List of the configured {@link CmsRelationType} objects.<p> 872 * 873 * @return an unmodifiable List of the configured {@link CmsRelationType} objects 874 */ 875 public List<CmsRelationType> getRelationTypes() { 876 877 return m_configuredRelationTypes; 878 } 879 880 /** 881 * Convenience method to get the initialized resource type instance for the given resource, 882 * with a fall back to special "unknown" resource types in case the resource type is not configured.<p> 883 * 884 * @param resource the resource to get the type for 885 * 886 * @return the initialized resource type instance for the given resource 887 */ 888 public I_CmsResourceType getResourceType(CmsResource resource) { 889 890 I_CmsResourceType result = m_configuration.getResourceTypeById(resource.getTypeId()); 891 if (result == null) { 892 // this resource type is unknown, return the default files instead 893 if (resource.isFolder()) { 894 // resource is a folder 895 if (m_restypeUnknownFolder != null) { 896 result = m_restypeUnknownFolder; 897 } else { 898 result = m_configuration.getResourceTypeByName(CmsResourceTypeFolder.getStaticTypeName()); 899 } 900 } else { 901 // resource is a file 902 if (m_restypeUnknownFile != null) { 903 result = m_restypeUnknownFile; 904 } else { 905 result = m_configuration.getResourceTypeByName(CmsResourceTypeBinary.getStaticTypeName()); 906 } 907 } 908 } 909 return result; 910 } 911 912 /** 913 * Returns the initialized resource type instance for the given id.<p> 914 * 915 * @param typeId the id of the resource type to get 916 * 917 * @return the initialized resource type instance for the given id 918 * 919 * @throws CmsLoaderException if no resource type is available for the given id 920 */ 921 public I_CmsResourceType getResourceType(int typeId) throws CmsLoaderException { 922 923 I_CmsResourceType result = m_configuration.getResourceTypeById(typeId); 924 if (result == null) { 925 throw new CmsLoaderException( 926 Messages.get().container(Messages.ERR_UNKNOWN_RESTYPE_ID_REQ_1, new Integer(typeId))); 927 } 928 return result; 929 } 930 931 /** 932 * Returns the initialized resource type instance for the given resource type name.<p> 933 * 934 * @param typeName the name of the resource type to get 935 * 936 * @return the initialized resource type instance for the given name 937 * 938 * @throws CmsLoaderException if no resource type is available for the given name 939 */ 940 public I_CmsResourceType getResourceType(String typeName) throws CmsLoaderException { 941 942 I_CmsResourceType result = m_configuration.getResourceTypeByName(typeName); 943 if (result != null) { 944 return result; 945 } 946 throw new CmsLoaderException(Messages.get().container(Messages.ERR_UNKNOWN_RESTYPE_NAME_REQ_1, typeName)); 947 } 948 949 /** 950 * Returns the (unmodifiable) list with all initialized resource types.<p> 951 * 952 * @return the (unmodifiable) list with all initialized resource types 953 */ 954 public List<I_CmsResourceType> getResourceTypes() { 955 956 return m_configuration.m_resourceTypeList; 957 } 958 959 /** 960 * Returns the (unmodifiable) list with all initialized resource types including unknown types.<p> 961 * 962 * @return the (unmodifiable) list with all initialized resource types including unknown types 963 */ 964 public List<I_CmsResourceType> getResourceTypesWithUnknown() { 965 966 return m_configuration.m_resourceTypeListWithUnknown; 967 } 968 969 /** 970 * The configured default type for files when the resource type is missing.<p> 971 * 972 * @return the configured default type for files 973 */ 974 public I_CmsResourceType getResTypeUnknownFile() { 975 976 return m_restypeUnknownFile; 977 } 978 979 /** 980 * The configured default type for folders when the resource type is missing.<p> 981 * 982 * @return The configured default type for folders 983 */ 984 public I_CmsResourceType getResTypeUnknownFolder() { 985 986 return m_restypeUnknownFolder; 987 } 988 989 /** 990 * Returns a template loader facade for the given file.<p> 991 * @param cms the current OpenCms user context 992 * @param resource the requested file 993 * @param templateProperty the property to read for the template 994 * 995 * @return a resource loader facade for the given file 996 * @throws CmsException if something goes wrong 997 */ 998 public CmsTemplateLoaderFacade getTemplateLoaderFacade(CmsObject cms, CmsResource resource, String templateProperty) 999 throws CmsException { 1000 1001 return getTemplateLoaderFacade(cms, null, resource, templateProperty); 1002 } 1003 1004 /** 1005 * Returns a template loader facade for the given file.<p> 1006 * @param cms the current OpenCms user context 1007 * @param request the current request 1008 * @param resource the requested file 1009 * @param templateProperty the property to read for the template 1010 * 1011 * @return a resource loader facade for the given file 1012 * @throws CmsException if something goes wrong 1013 */ 1014 public CmsTemplateLoaderFacade getTemplateLoaderFacade( 1015 CmsObject cms, 1016 HttpServletRequest request, 1017 CmsResource resource, 1018 String templateProperty) 1019 throws CmsException { 1020 1021 String templateProp = cms.readPropertyObject(resource, templateProperty, true).getValue(); 1022 CmsTemplateContext templateContext = null; 1023 String templateName = null; 1024 if (templateProp == null) { 1025 1026 // use default template, if template is not set 1027 templateProp = DEFAULT_TEMPLATE; 1028 NamedTemplate namedTemplate = readTemplateWithName(cms, templateProp); 1029 if (namedTemplate == null) { 1030 // no template property defined, this is a must for facade loaders 1031 throw new CmsLoaderException( 1032 Messages.get().container(Messages.ERR_NONDEF_PROP_2, templateProperty, cms.getSitePath(resource))); 1033 } 1034 templateName = namedTemplate.getName(); 1035 } else { 1036 if (CmsTemplateContextManager.hasPropertyPrefix(templateProp)) { 1037 templateContext = OpenCms.getTemplateContextManager().getTemplateContext( 1038 templateProp, 1039 cms, 1040 request, 1041 resource); 1042 if (templateContext != null) { 1043 templateProp = templateContext.getTemplatePath(); 1044 } 1045 } 1046 NamedTemplate namedTemplate = readTemplateWithName(cms, templateProp); 1047 if (namedTemplate == null) { 1048 namedTemplate = readTemplateWithName(cms, DEFAULT_TEMPLATE); 1049 if (namedTemplate != null) { 1050 templateProp = DEFAULT_TEMPLATE; 1051 templateName = namedTemplate.getName(); 1052 } 1053 } else { 1054 templateName = namedTemplate.getName(); 1055 } 1056 } 1057 CmsResource template = cms.readFile(templateProp, CmsResourceFilter.IGNORE_EXPIRATION); 1058 CmsTemplateLoaderFacade result = new CmsTemplateLoaderFacade(getLoader(template), resource, template); 1059 result.setTemplateContext(templateContext); 1060 result.setTemplateName(templateName); 1061 return result; 1062 1063 } 1064 1065 /** 1066 * Returns the XSD translator.<p> 1067 * 1068 * @return the XSD translator 1069 */ 1070 public CmsResourceTranslator getXsdTranslator() { 1071 1072 return m_xsdTranslator; 1073 } 1074 1075 /** 1076 * Checks if an initialized resource type instance equal to the given resource type is available.<p> 1077 * 1078 * @param type the resource type to check 1079 * @return <code>true</code> if such a resource type has been configured, <code>false</code> otherwise 1080 * 1081 * @see #getResourceType(String) 1082 * @see #getResourceType(int) 1083 */ 1084 public boolean hasResourceType(I_CmsResourceType type) { 1085 1086 return hasResourceType(type.getTypeName()); 1087 } 1088 1089 /** 1090 * Checks if an initialized resource type instance for the given resource type is is available.<p> 1091 * 1092 * @param typeId the id of the resource type to check 1093 * @return <code>true</code> if such a resource type has been configured, <code>false</code> otherwise 1094 * 1095 * @see #getResourceType(int) 1096 * 1097 * @deprecated 1098 * Use {@link #hasResourceType(I_CmsResourceType)} or {@link #hasResourceType(I_CmsResourceType)} instead. 1099 * Resource types should always be referenced either by its type class (preferred) or by type name. 1100 * Use of int based resource type references will be discontinued in a future OpenCms release. 1101 */ 1102 @Deprecated 1103 public boolean hasResourceType(int typeId) { 1104 1105 return m_configuration.getResourceTypeById(typeId) != null; 1106 } 1107 1108 /** 1109 * Checks if an initialized resource type instance for the given resource type name is available.<p> 1110 * 1111 * @param typeName the name of the resource type to check 1112 * @return <code>true</code> if such a resource type has been configured, <code>false</code> otherwise 1113 * 1114 * @see #getResourceType(String) 1115 */ 1116 public boolean hasResourceType(String typeName) { 1117 1118 return m_configuration.getResourceTypeByName(typeName) != null; 1119 } 1120 1121 /** 1122 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 1123 * 1124 * @throws CmsConfigurationException in case of duplicate resource types in the configuration 1125 */ 1126 public void initConfiguration() throws CmsConfigurationException { 1127 1128 if (CmsLog.INIT.isInfoEnabled()) { 1129 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LOADER_CONFIG_FINISHED_0)); 1130 } 1131 1132 m_resourceTypesFromXml = Collections.unmodifiableList(m_resourceTypesFromXml); 1133 m_loaderList = Collections.unmodifiableList(m_loaderList); 1134 Collections.sort(m_configuredMimeTypes); 1135 m_configuredMimeTypes = Collections.unmodifiableList(m_configuredMimeTypes); 1136 m_configuredRelationTypes = Collections.unmodifiableList(m_configuredRelationTypes); 1137 1138 // initialize the HTML converters 1139 initHtmlConverters(); 1140 m_configuredHtmlConverters = Collections.unmodifiableList(m_configuredHtmlConverters); 1141 1142 // initialize the resource types 1143 initResourceTypes(); 1144 // initialize the MIME types 1145 initMimeTypes(); 1146 } 1147 1148 /** 1149 * Initializes all additional resource types stored in the modules.<p> 1150 * 1151 * @param cms an initialized OpenCms user context with "module manager" role permissions 1152 * 1153 * @throws CmsRoleViolationException in case the provided OpenCms user context did not have "module manager" role permissions 1154 * @throws CmsConfigurationException in case of duplicate resource types in the configuration 1155 */ 1156 public synchronized void initialize(CmsObject cms) throws CmsRoleViolationException, CmsConfigurationException { 1157 1158 if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT) { 1159 // some simple test cases don't require this check 1160 OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER); 1161 } 1162 1163 // initialize the resource types 1164 initResourceTypes(); 1165 1166 // call initialize method on all resource types 1167 Iterator<I_CmsResourceType> i = m_configuration.m_resourceTypeList.iterator(); 1168 while (i.hasNext()) { 1169 I_CmsResourceType type = i.next(); 1170 type.initialize(cms); 1171 } 1172 1173 m_nameGenerator.setAdminCms(cms); 1174 1175 if (CmsLog.INIT.isInfoEnabled()) { 1176 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LOADER_CONFIG_FINISHED_0)); 1177 } 1178 } 1179 1180 /** 1181 * Loads the requested resource and writes the contents to the response stream.<p> 1182 * 1183 * @param req the current HTTP request 1184 * @param res the current HTTP response 1185 * @param cms the current OpenCms user context 1186 * @param resource the requested resource 1187 * @throws ServletException if something goes wrong 1188 * @throws IOException if something goes wrong 1189 * @throws CmsException if something goes wrong 1190 */ 1191 public void loadResource(CmsObject cms, CmsResource resource, HttpServletRequest req, HttpServletResponse res) 1192 throws ServletException, IOException, CmsException { 1193 1194 res.setContentType(getMimeType(resource.getName(), cms.getRequestContext().getEncoding())); 1195 I_CmsResourceLoader loader = getLoader(resource); 1196 loader.load(cms, resource, req, res); 1197 } 1198 1199 /** 1200 * Checks if there is a resource type with a given name whose id matches the given id.<p> 1201 * 1202 * This will return 'false' if no resource type with the given name is registered.<p> 1203 * 1204 * @param name a resource type name 1205 * @param id a resource type id 1206 * 1207 * @return true if a matching resource type with the given name and id was found 1208 */ 1209 public boolean matchResourceType(String name, int id) { 1210 1211 if (hasResourceType(name)) { 1212 try { 1213 return getResourceType(name).getTypeId() == id; 1214 } catch (Exception e) { 1215 // should never happen because we already checked with hasResourceType, still have to 1216 // catch it so the compiler is happy 1217 LOG.error(e.getLocalizedMessage(), e); 1218 return false; 1219 } 1220 } else { 1221 return false; 1222 } 1223 } 1224 1225 /** 1226 * Configures the URL name generator for XML contents.<p> 1227 * 1228 * @param nameGenerator the configured name generator class 1229 * 1230 * @throws CmsConfigurationException if something goes wrong 1231 */ 1232 public void setNameGenerator(I_CmsFileNameGenerator nameGenerator) throws CmsConfigurationException { 1233 1234 if (m_frozen) { 1235 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_NO_CONFIG_AFTER_STARTUP_0)); 1236 } 1237 m_nameGenerator = nameGenerator; 1238 1239 if (CmsLog.INIT.isInfoEnabled()) { 1240 CmsLog.INIT.info( 1241 Messages.get().getBundle().key(Messages.INIT_SET_NAME_GENERATOR_1, nameGenerator.getClass().getName())); 1242 } 1243 } 1244 1245 /** 1246 * Sets the folder, the file and the XSD translator.<p> 1247 * 1248 * @param folderTranslator the folder translator to set 1249 * @param fileTranslator the file translator to set 1250 * @param xsdTranslator the XSD translator to set 1251 */ 1252 public void setTranslators( 1253 CmsResourceTranslator folderTranslator, 1254 CmsResourceTranslator fileTranslator, 1255 CmsResourceTranslator xsdTranslator) { 1256 1257 m_folderTranslator = folderTranslator; 1258 m_fileTranslator = fileTranslator; 1259 m_xsdTranslator = xsdTranslator; 1260 } 1261 1262 /** 1263 * Shuts down this resource manage instance.<p> 1264 * 1265 * @throws Exception in case of errors during shutdown 1266 */ 1267 public synchronized void shutDown() throws Exception { 1268 1269 Iterator<I_CmsResourceLoader> it = m_loaderList.iterator(); 1270 while (it.hasNext()) { 1271 // destroy all resource loaders 1272 I_CmsResourceLoader loader = it.next(); 1273 loader.destroy(); 1274 } 1275 1276 m_loaderList = null; 1277 m_loaders = null; 1278 m_collectorNameMappings = null; 1279 m_mimeTypes = null; 1280 m_configuredMimeTypes = null; 1281 m_configuredRelationTypes = null; 1282 m_configuredHtmlConverters = null; 1283 m_htmlConverters = null; 1284 1285 if (CmsLog.INIT.isInfoEnabled()) { 1286 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_1, this.getClass().getName())); 1287 } 1288 } 1289 1290 /** 1291 * Gets the template name for a template resource, using a cache for efficiency.<p> 1292 * 1293 * @param cms the current CMS context 1294 * @param resource the template resource 1295 * @return the template name 1296 * 1297 * @throws CmsException if something goes wrong 1298 */ 1299 private String getTemplateName(CmsObject cms, CmsResource resource) throws CmsException { 1300 1301 String templateName = (String)(m_templateNameCache.getCachedObject(cms, resource.getRootPath())); 1302 if (templateName == null) { 1303 CmsProperty nameProperty = cms.readPropertyObject( 1304 resource, 1305 CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, 1306 false); 1307 String nameFromProperty = ""; 1308 if (!nameProperty.isNullProperty()) { 1309 nameFromProperty = nameProperty.getValue(); 1310 } 1311 m_templateNameCache.putCachedObject(cms, resource.getRootPath(), nameFromProperty); 1312 return nameFromProperty; 1313 } else { 1314 return templateName; 1315 } 1316 } 1317 1318 /** 1319 * Initialize the HTML converters.<p> 1320 * 1321 * HTML converters are configured in the OpenCms <code>opencms-vfs.xml</code> configuration file.<p> 1322 * 1323 * For legacy reasons, the default JTidy HTML converter has to be loaded if no explicit HTML converters 1324 * are configured in the configuration file.<p> 1325 */ 1326 private void initHtmlConverters() { 1327 1328 // check if any HTML converter configuration were found 1329 if (m_configuredHtmlConverters.size() == 0) { 1330 // no converters configured, add default JTidy converter configuration 1331 String classJTidy = CmsHtmlConverterJTidy.class.getName(); 1332 m_configuredHtmlConverters.add( 1333 new CmsHtmlConverterOption(CmsHtmlConverter.PARAM_ENABLED, classJTidy, true)); 1334 m_configuredHtmlConverters.add(new CmsHtmlConverterOption(CmsHtmlConverter.PARAM_XHTML, classJTidy, true)); 1335 m_configuredHtmlConverters.add(new CmsHtmlConverterOption(CmsHtmlConverter.PARAM_WORD, classJTidy, true)); 1336 m_configuredHtmlConverters.add( 1337 new CmsHtmlConverterOption(CmsHtmlConverter.PARAM_REPLACE_PARAGRAPHS, classJTidy, true)); 1338 } 1339 1340 // initialize lookup map of configured HTML converters 1341 m_htmlConverters = new HashMap<String, String>(m_configuredHtmlConverters.size()); 1342 for (Iterator<CmsHtmlConverterOption> i = m_configuredHtmlConverters.iterator(); i.hasNext();) { 1343 CmsHtmlConverterOption converterOption = i.next(); 1344 m_htmlConverters.put(converterOption.getName(), converterOption.getClassName()); 1345 } 1346 } 1347 1348 /** 1349 * Initialize the MIME types.<p> 1350 * 1351 * MIME types are configured in the OpenCms <code>opencms-vfs.xml</code> configuration file.<p> 1352 * 1353 * For legacy reasons, the MIME types are also read from a file <code>"mimetypes.properties"</code> 1354 * that must be located in the default <code>"classes"</code> folder of the web application.<p> 1355 */ 1356 private void initMimeTypes() { 1357 1358 // legacy MIME type initialization: try to read properties file 1359 Properties mimeTypes = new Properties(); 1360 try { 1361 // first try: read MIME types from default package 1362 mimeTypes.load(getClass().getClassLoader().getResourceAsStream("mimetypes.properties")); 1363 } catch (Throwable t) { 1364 try { 1365 // second try: read MIME types from loader package (legacy reasons, there are no types by default) 1366 mimeTypes.load( 1367 getClass().getClassLoader().getResourceAsStream("org/opencms/loader/mimetypes.properties")); 1368 } catch (Throwable t2) { 1369 if (LOG.isInfoEnabled()) { 1370 LOG.info( 1371 Messages.get().getBundle().key( 1372 Messages.LOG_READ_MIMETYPES_FAILED_2, 1373 "mimetypes.properties", 1374 "org/opencms/loader/mimetypes.properties")); 1375 } 1376 } 1377 } 1378 1379 // initialize the Map with all available MIME types 1380 List<CmsMimeType> combinedMimeTypes = new ArrayList<CmsMimeType>( 1381 mimeTypes.size() + m_configuredMimeTypes.size()); 1382 // first add all MIME types from the configuration 1383 combinedMimeTypes.addAll(m_configuredMimeTypes); 1384 // now add the MIME types from the properties 1385 Iterator<Map.Entry<Object, Object>> i = mimeTypes.entrySet().iterator(); 1386 while (i.hasNext()) { 1387 Map.Entry<Object, Object> entry = i.next(); 1388 CmsMimeType mimeType = new CmsMimeType(entry.getKey().toString(), entry.getValue().toString(), false); 1389 if (!combinedMimeTypes.contains(mimeType)) { 1390 // make sure no MIME types from the XML configuration are overwritten 1391 combinedMimeTypes.add(mimeType); 1392 } 1393 } 1394 1395 // create a lookup Map for the MIME types 1396 m_mimeTypes = new HashMap<String, String>(mimeTypes.size()); 1397 Iterator<CmsMimeType> j = combinedMimeTypes.iterator(); 1398 while (j.hasNext()) { 1399 CmsMimeType mimeType = j.next(); 1400 m_mimeTypes.put(mimeType.getExtension(), mimeType.getType()); 1401 } 1402 1403 if (CmsLog.INIT.isInfoEnabled()) { 1404 CmsLog.INIT.info( 1405 Messages.get().getBundle().key(Messages.INIT_NUM_MIMETYPES_1, new Integer(m_mimeTypes.size()))); 1406 } 1407 } 1408 1409 /** 1410 * Adds a new resource type to the internal list of loaded resource types and initializes 1411 * options for the resource type.<p> 1412 * 1413 * @param resourceType the resource type to add 1414 * @param configuration the resource configuration 1415 */ 1416 private synchronized void initResourceType( 1417 I_CmsResourceType resourceType, 1418 CmsResourceManagerConfiguration configuration) { 1419 1420 // add the loader to the internal list of loaders 1421 configuration.addResourceType(resourceType); 1422 if (CmsLog.INIT.isInfoEnabled()) { 1423 CmsLog.INIT.info( 1424 Messages.get().getBundle().key( 1425 Messages.INIT_ADD_RESTYPE_3, 1426 resourceType.getTypeName(), 1427 new Integer(resourceType.getTypeId()), 1428 resourceType.getClass().getName())); 1429 } 1430 1431 // add the mappings 1432 List<String> mappings = resourceType.getConfiguredMappings(); 1433 Iterator<String> i = mappings.iterator(); 1434 while (i.hasNext()) { 1435 String mapping = i.next(); 1436 // only add this mapping if a mapping with this file extension does not 1437 // exist already 1438 if (!configuration.m_extensionMappings.containsKey(mapping)) { 1439 configuration.m_extensionMappings.put(mapping, resourceType.getTypeName()); 1440 if (CmsLog.INIT.isInfoEnabled()) { 1441 CmsLog.INIT.info( 1442 Messages.get().getBundle().key( 1443 Messages.INIT_MAP_RESTYPE_2, 1444 mapping, 1445 resourceType.getTypeName())); 1446 } 1447 } 1448 } 1449 } 1450 1451 /** 1452 * Initializes member variables required for storing the resource types.<p> 1453 * 1454 * @throws CmsConfigurationException in case of duplicate resource types in the configuration 1455 */ 1456 private synchronized void initResourceTypes() throws CmsConfigurationException { 1457 1458 if (CmsLog.INIT.isInfoEnabled()) { 1459 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_STARTING_LOADER_CONFIG_0)); 1460 } 1461 1462 CmsResourceManagerConfiguration newConfiguration = new CmsResourceManagerConfiguration(); 1463 1464 if (CmsLog.INIT.isInfoEnabled()) { 1465 CmsLog.INIT.info( 1466 Messages.get().getBundle().key( 1467 Messages.INIT_ADD_RESTYPE_FROM_FILE_2, 1468 new Integer(m_resourceTypesFromXml.size()), 1469 CmsVfsConfiguration.DEFAULT_XML_FILE_NAME)); 1470 } 1471 1472 // build a new resource type list from the resource types of the XML configuration 1473 Iterator<I_CmsResourceType> i; 1474 i = m_resourceTypesFromXml.iterator(); 1475 while (i.hasNext()) { 1476 I_CmsResourceType resourceType = i.next(); 1477 initResourceType(resourceType, newConfiguration); 1478 } 1479 1480 // add all resource types declared in the modules 1481 CmsModuleManager moduleManager = OpenCms.getModuleManager(); 1482 if (moduleManager != null) { 1483 Iterator<String> modules = moduleManager.getModuleNames().iterator(); 1484 while (modules.hasNext()) { 1485 CmsModule module = moduleManager.getModule(modules.next()); 1486 if ((module != null) && (module.getResourceTypes().size() > 0)) { 1487 // module contains resource types 1488 if (CmsLog.INIT.isInfoEnabled()) { 1489 CmsLog.INIT.info( 1490 Messages.get().getBundle().key( 1491 Messages.INIT_ADD_NUM_RESTYPES_FROM_MOD_2, 1492 new Integer(module.getResourceTypes().size()), 1493 module.getName())); 1494 } 1495 1496 Iterator<I_CmsResourceType> j = module.getResourceTypes().iterator(); 1497 while (j.hasNext()) { 1498 I_CmsResourceType resourceType = j.next(); 1499 I_CmsResourceType conflictingType = null; 1500 if (resourceType.getTypeId() == CmsResourceTypeUnknownFile.RESOURCE_TYPE_ID) { 1501 // default unknown file resource type 1502 if (m_restypeUnknownFile != null) { 1503 // error: already set 1504 conflictingType = m_restypeUnknownFile; 1505 } else { 1506 m_restypeUnknownFile = resourceType; 1507 continue; 1508 } 1509 } else if (resourceType.getTypeId() == CmsResourceTypeUnknownFolder.RESOURCE_TYPE_ID) { 1510 // default unknown folder resource type 1511 if (m_restypeUnknownFolder != null) { 1512 // error: already set 1513 conflictingType = m_restypeUnknownFolder; 1514 } else { 1515 m_restypeUnknownFile = resourceType; 1516 continue; 1517 } 1518 } else { 1519 // normal resource types 1520 conflictingType = newConfiguration.getResourceTypeById(resourceType.getTypeId()); 1521 } 1522 if (conflictingType != null) { 1523 throw new CmsConfigurationException( 1524 Messages.get().container( 1525 Messages.ERR_CONFLICTING_MODULE_RESOURCE_TYPES_5, 1526 new Object[] { 1527 resourceType.getTypeName(), 1528 new Integer(resourceType.getTypeId()), 1529 module.getName(), 1530 conflictingType.getTypeName(), 1531 new Integer(conflictingType.getTypeId())})); 1532 } 1533 initResourceType(resourceType, newConfiguration); 1534 } 1535 } 1536 } 1537 } 1538 1539 // freeze the current configuration 1540 newConfiguration.freeze(m_restypeUnknownFile, m_restypeUnknownFile); 1541 m_configuration = newConfiguration; 1542 m_frozen = true; 1543 1544 if (CmsLog.INIT.isInfoEnabled()) { 1545 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_RESOURCE_TYPE_INITIALIZED_0)); 1546 } 1547 } 1548 1549 /** 1550 * Reads a template resource together with its name.<p> 1551 * 1552 * @param cms the current CMS context 1553 * @param path the template path 1554 * 1555 * @return the template together with its name, or null if the template couldn't be read 1556 */ 1557 private NamedTemplate readTemplateWithName(CmsObject cms, String path) { 1558 1559 try { 1560 CmsResource resource = cms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION); 1561 String name = getTemplateName(cms, resource); 1562 return new NamedTemplate(resource, name); 1563 } catch (Exception e) { 1564 return null; 1565 } 1566 } 1567 1568}