001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.configuration; 029 030import org.opencms.db.CmsOnlineFolderOptions; 031import org.opencms.file.CmsProperty; 032import org.opencms.file.collectors.I_CmsResourceCollector; 033import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 034import org.opencms.file.types.CmsResourceTypeXmlContent; 035import org.opencms.file.types.I_CmsResourceType; 036import org.opencms.loader.CmsDefaultFileNameGenerator; 037import org.opencms.loader.CmsMimeType; 038import org.opencms.loader.CmsResourceManager; 039import org.opencms.loader.I_CmsResourceLoader; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.relations.CmsRelationType; 043import org.opencms.util.CmsHtmlConverterOption; 044import org.opencms.util.CmsResourceTranslator; 045import org.opencms.util.CmsStringUtil; 046import org.opencms.widgets.I_CmsWidget; 047import org.opencms.xml.CmsXmlContentTypeManager; 048import org.opencms.xml.types.I_CmsXmlSchemaType; 049 050import java.util.ArrayList; 051import java.util.Collections; 052import java.util.Iterator; 053import java.util.List; 054 055import org.apache.commons.digester3.Digester; 056import org.apache.commons.digester3.Rule; 057 058import org.dom4j.Element; 059import org.xml.sax.Attributes; 060 061/** 062 * VFS master configuration class.<p> 063 * 064 * @since 6.0.0 065 */ 066public class CmsVfsConfiguration extends A_CmsXmlConfiguration { 067 068 /** The adjust-links-folder attribute. */ 069 public static final String A_ADJUST_LINKS_FOLDER = "adjust-links-folder"; 070 071 /** The widget configuration attribute. */ 072 public static final String A_CONFIGURATION = "configuration"; 073 074 /** The widget attribute. */ 075 public static final String A_DEFAULTWIDGET = "defaultwidget"; 076 077 /** The extension attribute name. */ 078 public static final String A_EXTENSION = "extension"; 079 080 /** The source attribute name. */ 081 public static final String A_SOURCE = "source"; 082 083 /** The target attribute name. */ 084 public static final String A_TARGET = "target"; 085 086 /** The name of the DTD for this configuration. */ 087 public static final String CONFIGURATION_DTD_NAME = "opencms-vfs.dtd"; 088 089 /** The name of the default XML file for this configuration. */ 090 public static final String DEFAULT_XML_FILE_NAME = "opencms-vfs.xml"; 091 092 /** The collector node name. */ 093 public static final String N_COLLECTOR = "collector"; 094 095 /** The collectors node name. */ 096 public static final String N_COLLECTORS = "collectors"; 097 098 public static final String N_PATH = "path"; 099 100 /** The copy-resource node name.*/ 101 public static final String N_COPY_RESOURCE = "copy-resource"; 102 103 /** The copy-resources node name.*/ 104 public static final String N_COPY_RESOURCES = "copy-resources"; 105 106 /** The defaultfile node name. */ 107 public static final String N_DEFAULTFILE = "defaultfile"; 108 109 /** The defaultfiles node name. */ 110 public static final String N_DEFAULTFILES = "defaultfiles"; 111 112 /** File translations node name. */ 113 public static final String N_FILETRANSLATIONS = "filetranslations"; 114 115 /** Folder translations node name. */ 116 public static final String N_FOLDERTRANSLATIONS = "foldertranslations"; 117 118 /** The html-converter node name.*/ 119 public static final String N_HTML_CONVERTER = "html-converter"; 120 121 /** The html-converters node name.*/ 122 public static final String N_HTML_CONVERTERS = "html-converters"; 123 124 /** The node name of an individual resource loader. */ 125 public static final String N_LOADER = "loader"; 126 127 /** The mapping node name. */ 128 public static final String N_MAPPING = "mapping"; 129 130 /** The mappings node name. */ 131 public static final String N_MAPPINGS = "mappings"; 132 133 /** The mimetype node name. */ 134 public static final String N_MIMETYPE = "mimetype"; 135 136 /** The mimetypes node name. */ 137 public static final String N_MIMETYPES = "mimetypes"; 138 139 /** The properties node name. */ 140 public static final String N_PROPERTIES = "properties"; 141 142 /** The relation type node name. */ 143 public static final String N_RELATIONTYPE = "relationtype"; 144 145 /** The relation types node name. */ 146 public static final String N_RELATIONTYPES = "relationtypes"; 147 148 /** The resource loaders node name. */ 149 public static final String N_RESOURCELOADERS = "resourceloaders"; 150 151 /** The main resource node name. */ 152 public static final String N_RESOURCES = "resources"; 153 154 /** The resource types node name. */ 155 public static final String N_RESOURCETYPES = "resourcetypes"; 156 157 /** The schematype node name. */ 158 public static final String N_SCHEMATYPE = "schematype"; 159 160 /** The storage-policy node name. */ 161 public static final String N_STORAGE_POLICY = "storage-policy"; 162 163 /** The online-folders node name. */ 164 public static final String N_ONLINE_FOLDERS = "online-folders"; 165 166 /** The schematypes node name. */ 167 public static final String N_SCHEMATYPES = "schematypes"; 168 169 /** Individual translation node name. */ 170 public static final String N_TRANSLATION = "translation"; 171 172 /** The translations master node name. */ 173 public static final String N_TRANSLATIONS = "translations"; 174 175 /** The node name of an individual resource type. */ 176 public static final String N_TYPE = "type"; 177 178 /** The node name for the version history. */ 179 public static final String N_VERSIONHISTORY = "versionhistory"; 180 181 /** The main vfs configuration node name. */ 182 public static final String N_VFS = "vfs"; 183 184 /** The widget node name. */ 185 public static final String N_WIDGET = "widget"; 186 187 /** The widget alias node name. */ 188 public static final String N_WIDGET_ALIAS = "widget-alias"; 189 190 /** The widgets node name. */ 191 public static final String N_WIDGETS = "widgets"; 192 193 /** The xmlcontent node name. */ 194 public static final String N_XMLCONTENT = "xmlcontent"; 195 196 /** The xmlcontents node name. */ 197 public static final String N_XMLCONTENTS = "xmlcontents"; 198 199 /** XSD translations node name. */ 200 public static final String N_XSDTRANSLATIONS = "xsdtranslations"; 201 202 /** The namegenerator node name. */ 203 private static final String N_NAMEGENERATOR = "namegenerator"; 204 205 private CmsOnlineFolderOptions m_onlineFolderOptions = new CmsOnlineFolderOptions( 206 new ArrayList<>(), 207 new CmsParameterConfiguration()); 208 209 /** The configured XML content type manager. */ 210 CmsXmlContentTypeManager m_xmlContentTypeManager; 211 212 /** The list of configured default files. */ 213 private List<String> m_defaultFiles; 214 215 /** Controls if file translation is enabled. */ 216 private boolean m_fileTranslationEnabled; 217 218 /** The list of file translations. */ 219 private List<String> m_fileTranslations; 220 221 /** Controls if folder translation is enabled. */ 222 private boolean m_folderTranslationEnabled; 223 224 /** The list of folder translations. */ 225 private List<String> m_folderTranslations; 226 227 /** The configured resource manager. */ 228 private CmsResourceManager m_resourceManager; 229 230 /** The configured storage policy. */ 231 private CmsStoragePolicyConfiguration m_storagePolicyConfiguration; 232 233 /** Controls if XSD translation is enabled. */ 234 private boolean m_xsdTranslationEnabled; 235 236 /** The list of XSD translations. */ 237 private List<String> m_xsdTranslations; 238 239 /** 240 * Adds the resource type rules to the given digester.<p> 241 * 242 * @param digester the digester to add the rules to 243 */ 244 public static void addResourceTypeXmlRules(Digester digester) { 245 246 // add rules for resource types 247 digester.addFactoryCreate("*/" + N_RESOURCETYPES + "/" + N_TYPE, CmsDigesterResourceTypeCreationFactory.class); 248 digester.addSetNext("*/" + N_RESOURCETYPES + "/" + N_TYPE, I_CmsResourceType.ADD_RESOURCE_TYPE_METHOD); 249 250 // please note: the order of the rules is very important here, 251 // the "set next" rule (above) must be added _before_ the "call method" rule (below)! 252 // reason is digester will call the rule that was last added first 253 // here we must make sure that the resource type is initialized first (with the "call method" rule) 254 // before it is actually added to the resource type container (with the "set next" rule) 255 // otherwise there will be an empty resource type added to the container, and validation will not work 256 digester.addCallMethod( 257 "*/" + N_RESOURCETYPES + "/" + N_TYPE, 258 I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD, 259 3); 260 // please note: the resource types use a special version of the init method with 3 parameters 261 digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 0, A_NAME); 262 digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 1, A_ID); 263 digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 2, A_CLASS); 264 265 // add rules for default properties 266 digester.addObjectCreate( 267 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY, 268 CmsProperty.class); 269 digester.addCallMethod( 270 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_NAME, 271 "setName", 272 1); 273 digester.addCallParam( 274 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_NAME, 275 0); 276 277 digester.addCallMethod( 278 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE, 279 "setValue", 280 2); 281 digester.addCallParam( 282 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE, 283 0); 284 digester.addCallParam( 285 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE, 286 1, 287 A_TYPE); 288 289 digester.addSetNext( 290 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY, 291 "addDefaultProperty"); 292 293 // extension mapping rules 294 digester.addCallMethod( 295 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_MAPPINGS + "/" + N_MAPPING, 296 I_CmsResourceType.ADD_MAPPING_METHOD, 297 1); 298 digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_MAPPINGS + "/" + N_MAPPING, 0, A_SUFFIX); 299 300 digester.addCallMethod( 301 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES, 302 "setAdjustLinksFolder", 303 1); 304 digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES, 0, A_ADJUST_LINKS_FOLDER); 305 306 // copy resource rules 307 digester.addCallMethod( 308 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE, 309 "addCopyResource", 310 3); 311 digester.addCallParam( 312 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE, 313 0, 314 A_SOURCE); 315 digester.addCallParam( 316 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE, 317 1, 318 A_TARGET); 319 digester.addCallParam( 320 "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE, 321 2, 322 A_TYPE); 323 324 } 325 326 /** 327 * Creates the xml output for resourcetype nodes.<p> 328 * 329 * @param startNode the startnode to add all rescource types to 330 * @param resourceTypes the list of resource types 331 * @param module flag, signaling to add them module resource types or not 332 */ 333 public static void generateResourceTypeXml( 334 Element startNode, 335 List<I_CmsResourceType> resourceTypes, 336 boolean module) { 337 338 for (int i = 0; i < resourceTypes.size(); i++) { 339 I_CmsResourceType resType = resourceTypes.get(i); 340 // only add this resource type to the xml output, if it is no additional type defined 341 // in a module 342 if (resType.isAdditionalModuleResourceType() == module) { 343 Element resourceType = startNode.addElement(N_TYPE).addAttribute(A_CLASS, resType.getClassName()); 344 // add type id and type name 345 resourceType.addAttribute(A_NAME, resType.getTypeName()); 346 resourceType.addAttribute(A_ID, String.valueOf(resType.getTypeId())); 347 // add resource mappings 348 List<String> mappings = resType.getConfiguredMappings(); 349 if ((mappings != null) && (mappings.size() > 0)) { 350 Element mappingsNode = resourceType.addElement(N_MAPPINGS); 351 for (int j = 0; j < mappings.size(); j++) { 352 Element mapping = mappingsNode.addElement(N_MAPPING); 353 mapping.addAttribute(A_SUFFIX, mappings.get(j)); 354 } 355 } 356 // add default properties 357 List<CmsProperty> properties = resType.getConfiguredDefaultProperties(); 358 if (properties != null) { 359 if (properties.size() > 0) { 360 Element propertiesNode = resourceType.addElement(N_PROPERTIES); 361 Iterator<CmsProperty> p = properties.iterator(); 362 while (p.hasNext()) { 363 CmsProperty property = p.next(); 364 Element propertyNode = propertiesNode.addElement(N_PROPERTY); 365 propertyNode.addElement(N_NAME).addText(property.getName()); 366 if (property.getStructureValue() != null) { 367 propertyNode.addElement(N_VALUE).addCDATA(property.getStructureValue()); 368 } 369 if (property.getResourceValue() != null) { 370 propertyNode.addElement(N_VALUE).addAttribute(A_TYPE, CmsProperty.TYPE_SHARED).addCDATA( 371 property.getResourceValue()); 372 } 373 } 374 } 375 } 376 // add copy resources 377 List<CmsConfigurationCopyResource> copyRes = resType.getConfiguredCopyResources(); 378 if ((copyRes != null) && (copyRes.size() > 0)) { 379 Element copyResNode = resourceType.addElement(N_COPY_RESOURCES); 380 Iterator<CmsConfigurationCopyResource> p = copyRes.iterator(); 381 String adjustLinksFolder = resType.getAdjustLinksFolder(); 382 if (adjustLinksFolder != null) { 383 copyResNode.addAttribute(A_ADJUST_LINKS_FOLDER, adjustLinksFolder); 384 } 385 while (p.hasNext()) { 386 CmsConfigurationCopyResource cRes = p.next(); 387 Element cNode = copyResNode.addElement(N_COPY_RESOURCE); 388 cNode.addAttribute(A_SOURCE, cRes.getSource()); 389 if (!cRes.isTargetWasNull()) { 390 cNode.addAttribute(A_TARGET, cRes.getTarget()); 391 } 392 if (!cRes.isTypeWasNull()) { 393 cNode.addAttribute(A_TYPE, cRes.getTypeString()); 394 } 395 } 396 } 397 // add optional parameters 398 CmsParameterConfiguration configuration = resType.getConfiguration(); 399 if (configuration != null) { 400 List<String> ignore = null; 401 if ((resType instanceof CmsResourceTypeXmlContainerPage)) { 402 ignore = new ArrayList<String>(1); 403 ignore.add(CmsResourceTypeXmlContent.CONFIGURATION_SCHEMA); 404 } 405 configuration.appendToXml(resourceType, ignore); 406 } 407 } 408 } 409 } 410 411 /** 412 * Adds a directory default file.<p> 413 * 414 * @param defaultFile the directory default file to add 415 */ 416 public void addDefaultFile(String defaultFile) { 417 418 m_defaultFiles.add(defaultFile); 419 if (CmsLog.INIT.isInfoEnabled()) { 420 CmsLog.INIT.info( 421 Messages.get().getBundle().key( 422 Messages.INIT_VFS_DEFAULT_FILE_2, 423 Integer.valueOf(m_defaultFiles.size()), 424 defaultFile)); 425 } 426 } 427 428 /** 429 * Adds one file translation rule.<p> 430 * 431 * @param translation the file translation rule to add 432 */ 433 public void addFileTranslation(String translation) { 434 435 m_fileTranslations.add(translation); 436 if (CmsLog.INIT.isInfoEnabled()) { 437 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_FILE_TRANSLATION_1, translation)); 438 } 439 } 440 441 /** 442 * Adds one folder translation rule.<p> 443 * 444 * @param translation the folder translation rule to add 445 */ 446 public void addFolderTranslation(String translation) { 447 448 m_folderTranslations.add(translation); 449 if (CmsLog.INIT.isInfoEnabled()) { 450 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_FOLDER_TRANSLATION_1, translation)); 451 } 452 } 453 454 /** 455 * @see org.opencms.configuration.I_CmsXmlConfiguration#addXmlDigesterRules(org.apache.commons.digester3.Digester) 456 */ 457 public void addXmlDigesterRules(Digester digester) { 458 459 // add finish rule 460 digester.addCallMethod("*/" + N_VFS, "initializeFinished"); 461 462 // creation of the resource manager 463 digester.addObjectCreate("*/" + N_VFS + "/" + N_RESOURCES, CmsResourceManager.class); 464 digester.addCallMethod( 465 "*/" + N_VFS + "/" + N_RESOURCES, 466 I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD); 467 digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES, "setResourceManager"); 468 469 // add rules for resource loaders 470 digester.addObjectCreate( 471 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER, 472 CmsConfigurationException.class.getName(), 473 A_CLASS); 474 digester.addCallMethod( 475 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER, 476 I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD); 477 digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER, "addLoader"); 478 479 // add rules for resource types 480 addResourceTypeXmlRules(digester); 481 482 // add rules for storage policy 483 digester.addRule("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_STORAGE_POLICY, new Rule() { 484 485 @Override 486 public void begin(String namespace, String name, Attributes attributes) throws Exception { 487 488 CmsStoragePolicyConfiguration configuration = new CmsStoragePolicyConfiguration(); 489 configuration.setClassName(attributes.getValue(A_CLASS)); 490 getDigester().push(configuration); 491 } 492 493 @Override 494 public void end(String namespace, String name) throws Exception { 495 496 CmsStoragePolicyConfiguration configuration = getDigester().pop(); 497 configuration.initConfiguration(); 498 setStoragePolicyConfiguration(configuration); 499 } 500 }); 501 502 // add rules for VFS content collectors 503 digester.addCallMethod( 504 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR, 505 "addContentCollector", 506 2); 507 digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR, 0, A_CLASS); 508 digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR, 1, A_ORDER); 509 510 // add the name generator 511 digester.addObjectCreate( 512 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_NAMEGENERATOR, 513 CmsDefaultFileNameGenerator.class.getName(), 514 A_CLASS); 515 digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_NAMEGENERATOR, "setNameGenerator"); 516 517 // add MIME type rules 518 digester.addCallMethod( 519 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE, 520 "addMimeType", 521 2); 522 digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE, 0, A_EXTENSION); 523 digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE, 1, A_TYPE); 524 525 // add relation type rules 526 digester.addCallMethod( 527 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE, 528 "addRelationType", 529 2); 530 digester.addCallParam( 531 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE, 532 0, 533 A_NAME); 534 digester.addCallParam( 535 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE, 536 1, 537 A_TYPE); 538 539 // add html converter rules 540 digester.addCallMethod( 541 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER, 542 "addHtmlConverter", 543 2); 544 digester.addCallParam( 545 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER, 546 0, 547 A_NAME); 548 digester.addCallParam( 549 "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER, 550 1, 551 A_CLASS); 552 553 // generic <param> parameter rules 554 digester.addCallMethod( 555 "*/" + I_CmsXmlConfiguration.N_PARAM, 556 I_CmsConfigurationParameterHandler.ADD_PARAMETER_METHOD, 557 2); 558 digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 0, I_CmsXmlConfiguration.A_NAME); 559 digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 1); 560 561 // add rule for default files 562 digester.addCallMethod("*/" + N_VFS + "/" + N_DEFAULTFILES + "/" + N_DEFAULTFILE, "addDefaultFile", 1); 563 digester.addCallParam("*/" + N_VFS + "/" + N_DEFAULTFILES + "/" + N_DEFAULTFILE, 0, A_NAME); 564 565 // add rules for file translations 566 digester.addCallMethod( 567 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS + "/" + N_TRANSLATION, 568 "addFileTranslation", 569 0); 570 digester.addCallMethod( 571 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS, 572 "setFileTranslationEnabled", 573 1); 574 digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS, 0, A_ENABLED); 575 576 // add rules for file translations 577 digester.addCallMethod( 578 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS + "/" + N_TRANSLATION, 579 "addFolderTranslation", 580 0); 581 digester.addCallMethod( 582 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS, 583 "setFolderTranslationEnabled", 584 1); 585 digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS, 0, A_ENABLED); 586 587 // add rules for file translations 588 digester.addCallMethod( 589 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS + "/" + N_TRANSLATION, 590 "addXsdTranslation", 591 0); 592 digester.addCallMethod( 593 "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS, 594 "setXsdTranslationEnabled", 595 1); 596 digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS, 0, A_ENABLED); 597 598 // XML content type manager creation rules 599 digester.addObjectCreate("*/" + N_VFS + "/" + N_XMLCONTENT, CmsXmlContentTypeManager.class); 600 digester.addSetNext("*/" + N_VFS + "/" + N_XMLCONTENT, "setXmlContentTypeManager"); 601 602 // XML content widgets add rules 603 604 // Widget definitions. 605 // 'aliases' list is used/reset by the rule for widgets, and filled by the rule for aliases. 606 final List<String> aliases = new ArrayList<>(); 607 digester.addRule("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET, new Rule() { 608 609 private String m_className; 610 private String m_config; 611 612 @Override 613 public void begin(String namespace, String name, Attributes attributes) throws Exception { 614 615 m_className = attributes.getValue(A_CLASS); 616 m_config = attributes.getValue(A_CONFIGURATION); 617 String alias = attributes.getValue(A_ALIAS); 618 619 aliases.clear(); 620 if (alias != null) { 621 aliases.add(alias.trim()); 622 } 623 } 624 625 @Override 626 public void end(String namespace, String name) throws Exception { 627 628 CmsXmlContentTypeManager manager = getDigester().peek(); 629 List<String> aliasesCopy = new ArrayList<>(aliases); 630 manager.addWidget(m_className, aliasesCopy, m_config); 631 } 632 }); 633 634 digester.addRule( 635 "*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET + "/" + N_WIDGET_ALIAS, 636 new Rule() { 637 638 @Override 639 public void body(String namespace, String name, String text) throws Exception { 640 641 aliases.add(text.trim()); 642 } 643 644 }); 645 646 // XML content schema type add rules 647 digester.addCallMethod( 648 "*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE, 649 "addSchemaType", 650 2); 651 digester.addCallParam("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE, 0, A_CLASS); 652 digester.addCallParam( 653 "*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE, 654 1, 655 A_DEFAULTWIDGET); 656 657 final CmsParameterConfiguration onlineFolderParams = new CmsParameterConfiguration(); 658 final List<String> onlineFolderPaths = new ArrayList<>(); 659 digester.addRule("*/" + N_ONLINE_FOLDERS, new Rule() { 660 661 @Override 662 public void begin(String namespace, String name, Attributes attributes) throws Exception { 663 664 super.begin(namespace, name, attributes); 665 getDigester().push(new I_CmsConfigurationParameterHandler() { 666 667 @Override 668 public void addConfigurationParameter(String paramName, String paramValue) { 669 670 onlineFolderParams.add(paramName, paramValue); 671 } 672 673 @Override 674 public CmsParameterConfiguration getConfiguration() { 675 676 return onlineFolderParams; 677 678 } 679 680 @Override 681 public void initConfiguration() throws CmsConfigurationException { 682 683 // TODO Auto-generated method stub 684 685 } 686 }); 687 } 688 689 @Override 690 public void end(String namespace, String name) throws Exception { 691 692 getDigester().pop(); 693 m_onlineFolderOptions = new CmsOnlineFolderOptions(onlineFolderPaths, onlineFolderParams); 694 } 695 }); 696 digester.addRule("*/" + N_ONLINE_FOLDERS + "/" + N_PATH, new Rule() { 697 698 public void body(String namespace, String name, String text) throws Exception { 699 700 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(text)) { 701 onlineFolderPaths.add(text); 702 } 703 } 704 }); 705 } 706 707 /** 708 * Adds one XSD translation rule.<p> 709 * 710 * @param translation the XSD translation rule to add 711 */ 712 public void addXsdTranslation(String translation) { 713 714 m_xsdTranslations.add(translation); 715 if (CmsLog.INIT.isInfoEnabled()) { 716 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_XSD_TRANSLATION_1, translation)); 717 } 718 } 719 720 /** 721 * @see org.opencms.configuration.I_CmsXmlConfiguration#generateXml(org.dom4j.Element) 722 */ 723 public Element generateXml(Element parent) { 724 725 if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) { 726 m_resourceManager = OpenCms.getResourceManager(); 727 m_xmlContentTypeManager = OpenCms.getXmlContentTypeManager(); 728 m_defaultFiles = OpenCms.getDefaultFiles(); 729 } 730 731 // generate vfs node and subnodes 732 Element vfs = parent.addElement(N_VFS); 733 734 // add resources main element 735 Element resources = vfs.addElement(N_RESOURCES); 736 737 // add resource loader 738 Element resourceloadersElement = resources.addElement(N_RESOURCELOADERS); 739 for (I_CmsResourceLoader loader : m_resourceManager.getLoaders()) { 740 // add the loader node 741 Element loaderNode = resourceloadersElement.addElement(N_LOADER); 742 loaderNode.addAttribute(A_CLASS, loader.getClass().getName()); 743 CmsParameterConfiguration loaderConfiguration = loader.getConfiguration(); 744 if (loaderConfiguration != null) { 745 loaderConfiguration.appendToXml(loaderNode); 746 } 747 } 748 749 // add resource types 750 Element resourcetypesElement = resources.addElement(N_RESOURCETYPES); 751 List<I_CmsResourceType> resourceTypes = new ArrayList<I_CmsResourceType>(); 752 if (m_resourceManager.getResTypeUnknownFolder() != null) { 753 resourceTypes.add(m_resourceManager.getResTypeUnknownFolder()); 754 } 755 if (m_resourceManager.getResTypeUnknownFile() != null) { 756 resourceTypes.add(m_resourceManager.getResTypeUnknownFile()); 757 } 758 resourceTypes.addAll(m_resourceManager.getResourceTypes()); 759 generateResourceTypeXml(resourcetypesElement, resourceTypes, false); 760 761 if (m_storagePolicyConfiguration != null) { 762 Element storagePolicyElement = resources.addElement(N_STORAGE_POLICY); 763 storagePolicyElement.addAttribute(A_CLASS, m_storagePolicyConfiguration.getClassName()); 764 m_storagePolicyConfiguration.getConfiguration().appendToXml(storagePolicyElement); 765 } 766 767 // add VFS content collectors 768 Element collectorsElement = resources.addElement(N_COLLECTORS); 769 for (I_CmsResourceCollector collector : m_resourceManager.getRegisteredContentCollectors()) { 770 collectorsElement.addElement(N_COLLECTOR).addAttribute( 771 A_CLASS, 772 collector.getClass().getName()).addAttribute(A_ORDER, String.valueOf(collector.getOrder())); 773 } 774 775 Element namegeneratorElement = resources.addElement(N_NAMEGENERATOR); 776 String nameGeneratorClass = m_resourceManager.getNameGenerator().getClass().getName(); 777 namegeneratorElement.addAttribute(A_CLASS, nameGeneratorClass); 778 779 // add MIME types 780 Element mimeTypesElement = resources.addElement(N_MIMETYPES); 781 for (CmsMimeType type : m_resourceManager.getMimeTypes()) { 782 mimeTypesElement.addElement(N_MIMETYPE).addAttribute(A_EXTENSION, type.getExtension()).addAttribute( 783 A_TYPE, 784 type.getType()); 785 } 786 787 // add relation types 788 Element relationTypesElement = resources.addElement(N_RELATIONTYPES); 789 for (CmsRelationType type : m_resourceManager.getRelationTypes()) { 790 relationTypesElement.addElement(N_RELATIONTYPE).addAttribute(A_NAME, type.getName()).addAttribute( 791 A_TYPE, 792 type.getType()); 793 } 794 795 // HTML converter configuration 796 boolean writeConfig = false; 797 for (CmsHtmlConverterOption converter : m_resourceManager.getHtmlConverters()) { 798 if (!converter.isDefault()) { 799 // found a non default converter configuration, set flag to write configuration 800 writeConfig = true; 801 break; 802 } 803 } 804 if (writeConfig) { 805 // configuration is written because non default options were found 806 Element htmlConvertersElement = resources.addElement(N_HTML_CONVERTERS); 807 for (CmsHtmlConverterOption converter : m_resourceManager.getHtmlConverters()) { 808 Element converterElement = htmlConvertersElement.addElement(N_HTML_CONVERTER).addAttribute( 809 A_NAME, 810 converter.getName()); 811 converterElement.addAttribute(A_CLASS, converter.getClassName()); 812 } 813 } 814 815 // add default file names 816 Element defaultFileElement = vfs.addElement(N_DEFAULTFILES); 817 for (String element : m_defaultFiles) { 818 defaultFileElement.addElement(N_DEFAULTFILE).addAttribute(A_NAME, element); 819 } 820 821 // add translation rules 822 Element translationsElement = vfs.addElement(N_TRANSLATIONS); 823 824 // file translation rules 825 Element fileTransElement = translationsElement.addElement(N_FILETRANSLATIONS).addAttribute( 826 A_ENABLED, 827 String.valueOf(m_fileTranslationEnabled)); 828 for (String translation : m_fileTranslations) { 829 fileTransElement.addElement(N_TRANSLATION).setText(translation); 830 } 831 832 // folder translation rules 833 Element folderTransElement = translationsElement.addElement(N_FOLDERTRANSLATIONS).addAttribute( 834 A_ENABLED, 835 String.valueOf(m_folderTranslationEnabled)); 836 for (String translation : m_folderTranslations) { 837 folderTransElement.addElement(N_TRANSLATION).setText(translation); 838 } 839 840 // XSD translation rules 841 Element xsdTransElement = translationsElement.addElement(N_XSDTRANSLATIONS).addAttribute( 842 A_ENABLED, 843 String.valueOf(m_xsdTranslationEnabled)); 844 for (String translation : m_xsdTranslations) { 845 xsdTransElement.addElement(N_TRANSLATION).setText(translation); 846 } 847 848 Element onlineFoldersElement = vfs.addElement(N_ONLINE_FOLDERS); 849 for (String path : m_onlineFolderOptions.getPaths()) { 850 Element pathElem = onlineFoldersElement.addElement(N_PATH); 851 pathElem.setText(path); 852 } 853 for (String key : m_onlineFolderOptions.getParams().keySet()) { 854 Element paramElem = onlineFoldersElement.addElement(N_PARAM); 855 paramElem.addAttribute(A_NAME, key); 856 paramElem.setText(m_onlineFolderOptions.getParams().get(key)); 857 } 858 859 // XML content configuration 860 Element xmlContentsElement = vfs.addElement(N_XMLCONTENT); 861 862 // XML widgets 863 Element xmlWidgetsElement = xmlContentsElement.addElement(N_WIDGETS); 864 for (String widget : m_xmlContentTypeManager.getRegisteredWidgetNames()) { 865 Element widgetElement = xmlWidgetsElement.addElement(N_WIDGET).addAttribute(A_CLASS, widget); 866 for (String alias : m_xmlContentTypeManager.getRegisteredWidgetAliases(widget)) { 867 widgetElement.addElement(N_WIDGET_ALIAS).addText(alias); 868 } 869 String defaultConfiguration = m_xmlContentTypeManager.getWidgetDefaultConfiguration(widget); 870 if (CmsStringUtil.isNotEmpty(defaultConfiguration)) { 871 widgetElement.addAttribute(A_CONFIGURATION, defaultConfiguration); 872 } 873 } 874 875 // XML content types 876 Element xmlSchemaTypesElement = xmlContentsElement.addElement(N_SCHEMATYPES); 877 for (I_CmsXmlSchemaType type : m_xmlContentTypeManager.getRegisteredSchemaTypes()) { 878 I_CmsWidget widget = m_xmlContentTypeManager.getWidgetDefault(type.getTypeName()); 879 xmlSchemaTypesElement.addElement(N_SCHEMATYPE).addAttribute( 880 A_CLASS, 881 type.getClass().getName()).addAttribute(A_DEFAULTWIDGET, widget.getClass().getName()); 882 } 883 884 // return the vfs node 885 return vfs; 886 } 887 888 /** 889 * Returns the (unmodifiable) list of configured directory default files.<p> 890 * 891 * @return the (unmodifiable) list of configured directory default files 892 */ 893 public List<String> getDefaultFiles() { 894 895 return Collections.unmodifiableList(m_defaultFiles); 896 } 897 898 /** 899 * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdFilename() 900 */ 901 public String getDtdFilename() { 902 903 return CONFIGURATION_DTD_NAME; 904 } 905 906 /** 907 * Returns the file resource translator that has been initialized 908 * with the configured file translation rules.<p> 909 * 910 * @return the file resource translator 911 */ 912 public CmsResourceTranslator getFileTranslator() { 913 914 String[] array = new String[0]; 915 if (m_fileTranslationEnabled) { 916 array = new String[m_fileTranslations.size()]; 917 for (int i = 0; i < m_fileTranslations.size(); i++) { 918 array[i] = m_fileTranslations.get(i); 919 } 920 } 921 return new CmsResourceTranslator(array, true); 922 } 923 924 /** 925 * Returns the folder resource translator that has been initialized 926 * with the configured folder translation rules.<p> 927 * 928 * @return the folder resource translator 929 */ 930 public CmsResourceTranslator getFolderTranslator() { 931 932 String[] array = new String[0]; 933 if (m_folderTranslationEnabled) { 934 array = new String[m_folderTranslations.size()]; 935 for (int i = 0; i < m_folderTranslations.size(); i++) { 936 array[i] = m_folderTranslations.get(i); 937 } 938 } 939 return new CmsResourceTranslator(array, false); 940 } 941 942 /** 943 * Gets the configured online folder options. 944 * 945 * @return the online folder options 946 */ 947 public CmsOnlineFolderOptions getOnlineFolderOptions() { 948 949 return m_onlineFolderOptions; 950 } 951 952 /** 953 * Returns the initialized resource manager.<p> 954 * 955 * @return the initialized resource manager 956 */ 957 public CmsResourceManager getResourceManager() { 958 959 return m_resourceManager; 960 } 961 962 /** 963 * Returns the configured storage policy configuration.<p> 964 * 965 * @return the configured storage policy configuration 966 */ 967 public CmsStoragePolicyConfiguration getStoragePolicyConfiguration() { 968 969 return m_storagePolicyConfiguration; 970 } 971 972 /** 973 * Returns the configured XML content type manager.<p> 974 * 975 * @return the configured XML content type manager 976 */ 977 public CmsXmlContentTypeManager getXmlContentTypeManager() { 978 979 return m_xmlContentTypeManager; 980 } 981 982 /** 983 * Returns the XSD translator that has been initialized 984 * with the configured XSD translation rules.<p> 985 * 986 * @return the XSD translator 987 */ 988 public CmsResourceTranslator getXsdTranslator() { 989 990 String[] array = m_xsdTranslationEnabled ? new String[m_xsdTranslations.size()] : new String[0]; 991 for (int i = 0; i < m_xsdTranslations.size(); i++) { 992 array[i] = m_xsdTranslations.get(i); 993 } 994 return new CmsResourceTranslator(array, true); 995 } 996 997 /** 998 * Will be called when configuration of this object is finished.<p> 999 */ 1000 public void initializeFinished() { 1001 1002 if (CmsLog.INIT.isInfoEnabled()) { 1003 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_CONFIG_FINISHED_0)); 1004 } 1005 } 1006 1007 /** 1008 * Enables or disables the file translation rules.<p> 1009 * 1010 * @param value if <code>"true"</code>, file translation is enabled, otherwise it is disabled 1011 */ 1012 public void setFileTranslationEnabled(String value) { 1013 1014 m_fileTranslationEnabled = Boolean.valueOf(value).booleanValue(); 1015 if (CmsLog.INIT.isInfoEnabled()) { 1016 if (m_fileTranslationEnabled) { 1017 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FILE_TRANSLATION_ENABLE_0)); 1018 } else { 1019 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FILE_TRANSLATION_DISABLE_0)); 1020 } 1021 } 1022 } 1023 1024 /** 1025 * Enables or disables the folder translation rules.<p> 1026 * 1027 * @param value if <code>"true"</code>, folder translation is enabled, otherwise it is disabled 1028 */ 1029 public void setFolderTranslationEnabled(String value) { 1030 1031 m_folderTranslationEnabled = Boolean.valueOf(value).booleanValue(); 1032 if (CmsLog.INIT.isInfoEnabled()) { 1033 if (m_folderTranslationEnabled) { 1034 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FOLDER_TRANSLATION_ENABLE_0)); 1035 } else { 1036 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FOLDER_TRANSLATION_DISABLE_0)); 1037 } 1038 } 1039 } 1040 1041 /** 1042 * Sets the generated resource manager.<p> 1043 * 1044 * @param manager the resource manager to set 1045 */ 1046 public void setResourceManager(CmsResourceManager manager) { 1047 1048 m_resourceManager = manager; 1049 } 1050 1051 /** 1052 * Sets the configured storage policy configuration.<p> 1053 * 1054 * @param storagePolicyConfiguration the storage policy configuration 1055 */ 1056 public void setStoragePolicyConfiguration(CmsStoragePolicyConfiguration storagePolicyConfiguration) { 1057 1058 m_storagePolicyConfiguration = storagePolicyConfiguration; 1059 } 1060 1061 /** 1062 * Sets the generated XML content type manager.<p> 1063 * 1064 * @param manager the generated XML content type manager to set 1065 */ 1066 public void setXmlContentTypeManager(CmsXmlContentTypeManager manager) { 1067 1068 if (CmsLog.INIT.isInfoEnabled()) { 1069 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XML_CONTENT_FINISHED_0)); 1070 } 1071 m_xmlContentTypeManager = manager; 1072 } 1073 1074 /** 1075 * Enables or disables the XSD translation rules.<p> 1076 * 1077 * @param value if <code>"true"</code>, XSD translation is enabled, otherwise it is disabled 1078 */ 1079 public void setXsdTranslationEnabled(String value) { 1080 1081 m_xsdTranslationEnabled = Boolean.valueOf(value).booleanValue(); 1082 if (CmsLog.INIT.isInfoEnabled()) { 1083 if (m_xsdTranslationEnabled) { 1084 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XSD_TRANSLATION_ENABLE_0)); 1085 } else { 1086 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XSD_TRANSLATION_DISABLE_0)); 1087 } 1088 } 1089 } 1090 1091 /** 1092 * @see org.opencms.configuration.A_CmsXmlConfiguration#initMembers() 1093 */ 1094 @Override 1095 protected void initMembers() { 1096 1097 setXmlFileName(DEFAULT_XML_FILE_NAME); 1098 m_fileTranslations = new ArrayList<String>(); 1099 m_folderTranslations = new ArrayList<String>(); 1100 m_xsdTranslations = new ArrayList<String>(); 1101 m_defaultFiles = new ArrayList<String>(); 1102 if (CmsLog.INIT.isInfoEnabled()) { 1103 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_CONFIG_INIT_0)); 1104 } 1105 } 1106}