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