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.module; 029 030import org.opencms.configuration.CmsConfigurationException; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProject; 033import org.opencms.file.types.I_CmsResourceType; 034import org.opencms.i18n.CmsMessageContainer; 035import org.opencms.importexport.CmsExport; 036import org.opencms.importexport.CmsExportParameters; 037import org.opencms.importexport.CmsImport; 038import org.opencms.importexport.CmsImportExportException; 039import org.opencms.importexport.CmsImportExportManager; 040import org.opencms.importexport.CmsImportHelper; 041import org.opencms.importexport.CmsImportParameters; 042import org.opencms.importexport.I_CmsImportExportHandler; 043import org.opencms.main.CmsException; 044import org.opencms.main.CmsLog; 045import org.opencms.main.CmsShell; 046import org.opencms.main.CmsSystemInfo; 047import org.opencms.main.OpenCms; 048import org.opencms.module.CmsModuleXmlHandler.XmlWriteMode; 049import org.opencms.report.CmsHtmlReport; 050import org.opencms.report.I_CmsReport; 051import org.opencms.security.CmsRole; 052import org.opencms.security.CmsRoleViolationException; 053import org.opencms.security.CmsSecurityException; 054import org.opencms.util.CmsFileUtil; 055import org.opencms.util.CmsMacroResolver; 056import org.opencms.util.CmsStringUtil; 057import org.opencms.xml.CmsXmlErrorHandler; 058import org.opencms.xml.CmsXmlException; 059 060import java.io.ByteArrayInputStream; 061import java.io.ByteArrayOutputStream; 062import java.io.File; 063import java.io.FileInputStream; 064import java.io.IOException; 065import java.io.InputStream; 066import java.io.PrintStream; 067import java.util.ArrayList; 068import java.util.Arrays; 069import java.util.Collections; 070import java.util.List; 071import java.util.zip.ZipEntry; 072import java.util.zip.ZipFile; 073 074import org.apache.commons.digester3.Digester; 075import org.apache.commons.digester3.Rule; 076import org.apache.commons.logging.Log; 077 078import org.dom4j.Document; 079import org.dom4j.Element; 080import org.xml.sax.SAXException; 081 082/** 083 * Import/export handler implementation for Cms modules.<p> 084 * 085 * @since 6.0.0 086 */ 087public class CmsModuleImportExportHandler implements I_CmsImportExportHandler { 088 089 /** The log object for this class. */ 090 private static final Log LOG = CmsLog.getLog(CmsModuleImportExportHandler.class); 091 092 /** The VFS resources to be exported additionally with the module.<p> */ 093 private List<String> m_additionalResources; 094 095 /** The description of this import/export handler.<p> */ 096 private String m_description; 097 098 /** The name of the export file in the real file system.<p> */ 099 private String m_fileName; 100 101 /** The module imported with the digester. */ 102 private CmsModule m_importedModule; 103 104 /** The import parameters. */ 105 private CmsImportParameters m_importParams; 106 107 /** The (package) name of the module to be exported.<p> */ 108 private String m_moduleName; 109 110 /** 111 * Creates a new Cms module import/export handler.<p> 112 */ 113 public CmsModuleImportExportHandler() { 114 115 super(); 116 m_description = org.opencms.importexport.Messages.get().getBundle().key( 117 org.opencms.importexport.Messages.GUI_CMSIMPORTHANDLER_DEFAULT_DESC_0); 118 } 119 120 /** 121 * Gets the module export handler containing all resources used in the module export.<p> 122 * @param cms the {@link CmsObject} used by to set up the handler. The object's site root might be adjusted to the import site of the module. 123 * @param module The module to export 124 * @param handlerDescription A description of the export handler, shown when the export thread using the handler runs. 125 * @return CmsModuleImportExportHandler with all module resources 126 */ 127 public static CmsModuleImportExportHandler getExportHandler( 128 CmsObject cms, 129 final CmsModule module, 130 final String handlerDescription) { 131 132 // check if all resources are valid 133 List<String> resListCopy = new ArrayList<String>(); 134 135 String moduleName = module.getName(); 136 137 try { 138 cms = OpenCms.initCmsObject(cms); 139 String importSite = module.getSite(); 140 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(importSite)) { 141 cms.getRequestContext().setSiteRoot(importSite); 142 } 143 } catch (CmsException e) { 144 // should never happen 145 LOG.error(e.getLocalizedMessage(), e); 146 } 147 try { 148 resListCopy = CmsModule.calculateModuleResourceNames(cms, module); 149 } catch (CmsException e) { 150 // some resource did not exist / could not be read 151 if (LOG.isInfoEnabled()) { 152 LOG.warn(Messages.get().getBundle().key(Messages.ERR_READ_MODULE_RESOURCES_1, module.getName()), e); 153 } 154 } 155 resListCopy = CmsFileUtil.removeRedundancies(resListCopy); 156 String[] resources = new String[resListCopy.size()]; 157 158 for (int i = 0; i < resListCopy.size(); i++) { 159 resources[i] = resListCopy.get(i); 160 } 161 162 String filename = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf( 163 OpenCms.getSystemInfo().getPackagesRfsPath() 164 + CmsSystemInfo.FOLDER_MODULES 165 + moduleName 166 + "_" 167 + "%(version)"); 168 169 CmsModuleImportExportHandler moduleExportHandler = new CmsModuleImportExportHandler(); 170 moduleExportHandler.setFileName(filename); 171 moduleExportHandler.setModuleName(moduleName.replace('\\', '/')); 172 moduleExportHandler.setAdditionalResources(resources); 173 moduleExportHandler.setDescription(handlerDescription); 174 175 return moduleExportHandler; 176 } 177 178 /** 179 * Reads a module object from an external file source.<p> 180 * 181 * @param importResource the name of the input source 182 * 183 * @return the imported module 184 * 185 * @throws CmsConfigurationException if the module could not be imported 186 */ 187 public static CmsModule readModuleFromImport(String importResource) throws CmsConfigurationException { 188 189 // instantiate Digester and enable XML validation 190 Digester digester = new Digester(); 191 digester.setUseContextClassLoader(true); 192 digester.setValidating(false); 193 digester.setRuleNamespaceURI(null); 194 digester.setErrorHandler(new CmsXmlErrorHandler(importResource)); 195 196 // add this class to the Digester 197 CmsModuleImportExportHandler handler = new CmsModuleImportExportHandler(); 198 final String[] version = new String[] {null}; 199 digester.push(handler); 200 201 digester.addRule("*/export_version", new Rule() { 202 203 @Override 204 public void body(String namespace, String name, String text) throws Exception { 205 206 version[0] = text.trim(); 207 } 208 209 }); 210 CmsModuleXmlHandler.addXmlDigesterRules(digester); 211 212 InputStream stream = null; 213 ZipFile importZip = null; 214 215 try { 216 File file = new File(importResource); 217 if (!file.exists()) { 218 throw new IOException("readModuleFromImport: Path '" + importResource + "' does not exist."); 219 } 220 if (file.isFile()) { 221 importZip = new ZipFile(importResource); 222 ZipEntry entry = importZip.getEntry(CmsImportExportManager.EXPORT_MANIFEST); 223 if (entry != null) { 224 stream = importZip.getInputStream(entry); 225 } else { 226 CmsMessageContainer message = Messages.get().container( 227 Messages.ERR_NO_MANIFEST_MODULE_IMPORT_1, 228 importResource); 229 LOG.error(message.key()); 230 throw new CmsConfigurationException(message); 231 } 232 } else if (file.isDirectory()) { 233 file = new File(file, CmsImportExportManager.EXPORT_MANIFEST); 234 stream = new FileInputStream(file); 235 } 236 237 // start the parsing process 238 digester.parse(stream); 239 } catch (IOException e) { 240 CmsMessageContainer message = Messages.get().container(Messages.ERR_IO_MODULE_IMPORT_1, importResource); 241 LOG.error(message.key(), e); 242 throw new CmsConfigurationException(message, e); 243 } catch (SAXException e) { 244 CmsMessageContainer message = Messages.get().container(Messages.ERR_SAX_MODULE_IMPORT_1, importResource); 245 LOG.error(message.key(), e); 246 throw new CmsConfigurationException(message, e); 247 } finally { 248 try { 249 if (importZip != null) { 250 importZip.close(); 251 } 252 if (stream != null) { 253 stream.close(); 254 } 255 } catch (Exception e) { 256 // noop 257 } 258 } 259 260 CmsModule importedModule = handler.getModule(); 261 // the digester must have set the module now 262 if (importedModule == null) { 263 throw new CmsConfigurationException( 264 Messages.get().container(Messages.ERR_IMPORT_MOD_ALREADY_INSTALLED_1, importResource)); 265 } else { 266 importedModule.setExportVersion(version[0]); 267 } 268 269 return importedModule; 270 } 271 272 /** 273 * Reads a module object from an external file source.<p> 274 * 275 * @param manifest the manifest data 276 * 277 * @return the imported module 278 * 279 * @throws CmsConfigurationException if the module could not be imported 280 */ 281 public static CmsModule readModuleFromManifest(byte[] manifest) throws CmsConfigurationException { 282 283 // instantiate Digester and enable XML validation 284 Digester digester = new Digester(); 285 digester.setUseContextClassLoader(true); 286 digester.setValidating(false); 287 digester.setRuleNamespaceURI(null); 288 digester.setErrorHandler(new CmsXmlErrorHandler("manifest data")); 289 290 // add this class to the Digester 291 CmsModuleImportExportHandler handler = new CmsModuleImportExportHandler(); 292 final String[] version = new String[] {null}; 293 digester.push(handler); 294 295 digester.addRule("*/export_version", new Rule() { 296 297 @Override 298 public void body(String namespace, String name, String text) throws Exception { 299 300 version[0] = text.trim(); 301 } 302 303 }); 304 CmsModuleXmlHandler.addXmlDigesterRules(digester); 305 306 InputStream stream = new ByteArrayInputStream(manifest); 307 308 try { 309 digester.parse(stream); 310 } catch (IOException e) { 311 CmsMessageContainer message = Messages.get().container(Messages.ERR_IO_MODULE_IMPORT_1, "manifest data"); 312 LOG.error(message.key(), e); 313 throw new CmsConfigurationException(message, e); 314 } catch (SAXException e) { 315 CmsMessageContainer message = Messages.get().container(Messages.ERR_SAX_MODULE_IMPORT_1, "manifest data"); 316 LOG.error(message.key(), e); 317 throw new CmsConfigurationException(message, e); 318 } 319 CmsModule importedModule = handler.getModule(); 320 // the digester must have set the module now 321 if (importedModule == null) { 322 throw new CmsConfigurationException( 323 Messages.get().container(Messages.ERR_IMPORT_MOD_ALREADY_INSTALLED_1, "manifest data")); 324 } else { 325 importedModule.setExportVersion(version[0]); 326 } 327 328 return importedModule; 329 } 330 331 /** 332 * Writes the messages for starting an import to the given report.<p> 333 * 334 * @param report the report to write to 335 * @param modulePackageName the module name 336 */ 337 public static void reportBeginImport(I_CmsReport report, String modulePackageName) { 338 339 report.print(Messages.get().container(Messages.RPT_IMPORT_MODULE_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 340 if (report instanceof CmsHtmlReport) { 341 report.print( 342 org.opencms.report.Messages.get().container( 343 org.opencms.report.Messages.RPT_ARGUMENT_1, 344 "<i>" + modulePackageName + "</i>")); 345 } else { 346 report.print( 347 org.opencms.report.Messages.get().container( 348 org.opencms.report.Messages.RPT_ARGUMENT_1, 349 modulePackageName)); 350 } 351 report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 352 } 353 354 /** 355 * Writes the messages for finishing an import to the given report.<p> 356 * 357 * @param report the report to write to 358 */ 359 public static void reportEndImport(I_CmsReport report) { 360 361 report.println(Messages.get().container(Messages.RPT_IMPORT_MODULE_END_0), I_CmsReport.FORMAT_HEADLINE); 362 } 363 364 /** 365 * @see org.opencms.importexport.I_CmsImportExportHandler#exportData(org.opencms.file.CmsObject, org.opencms.report.I_CmsReport) 366 */ 367 public void exportData(CmsObject cms, I_CmsReport report) 368 throws CmsConfigurationException, CmsImportExportException, CmsRoleViolationException { 369 370 // check if the user has the required permissions 371 OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER); 372 373 report.print(Messages.get().container(Messages.RPT_EXPORT_MODULE_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 374 if (report instanceof CmsHtmlReport) { 375 report.print( 376 org.opencms.report.Messages.get().container( 377 org.opencms.report.Messages.RPT_ARGUMENT_1, 378 "<i>" + getModuleName() + "</i>")); 379 380 } else { 381 report.print( 382 org.opencms.report.Messages.get().container( 383 org.opencms.report.Messages.RPT_ARGUMENT_1, 384 getModuleName())); 385 } 386 report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 387 388 if (!OpenCms.getModuleManager().hasModule(getModuleName())) { 389 // module not available 390 throw new CmsConfigurationException( 391 Messages.get().container(Messages.ERR_NO_MOD_FOR_EXPORT_1, getModuleName())); 392 } 393 394 // generate module XML 395 CmsModule module = OpenCms.getModuleManager().getModule(getModuleName()); 396 boolean shouldIncrementVersion; 397 try { 398 shouldIncrementVersion = module.isAutoIncrement() 399 && (module.getVersion().isUpdated() || module.shouldIncrementVersionBasedOnResources(cms)); 400 } catch (CmsException e) { 401 shouldIncrementVersion = false; 402 LOG.error(e.getLocalizedMessage(), e); 403 } 404 module.getVersion().setUpdated(false); 405 if (shouldIncrementVersion) { 406 module.getVersion().increment(); 407 module.setCheckpointTime(System.currentTimeMillis()); 408 OpenCms.getModuleManager().updateModuleConfiguration(); 409 } 410 411 Element moduleElement = CmsModuleXmlHandler.generateXml(module, XmlWriteMode.manifest); 412 413 CmsExportParameters params = new CmsExportParameters( 414 getFileName(), 415 moduleElement, 416 true, 417 false, 418 false, 419 getAdditionalResources(), 420 true, 421 true, 422 0, 423 true, 424 false, 425 module.getExportMode(), 426 // provide the extra resources only in case of excluded resources, otherwise not needed 427 ((null == module.getExcludeResources()) || module.getExcludeResources().isEmpty()) 428 ? null 429 : module.getResources()); 430 431 // export the module using the standard export 432 CmsObject exportCms = cms; 433 String importSite = module.getSite(); 434 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(importSite)) { 435 try { 436 exportCms = OpenCms.initCmsObject(exportCms); 437 exportCms.getRequestContext().setSiteRoot(importSite); 438 } catch (Exception e) { 439 LOG.error(e.getLocalizedMessage(), e); 440 } 441 } 442 new CmsExport(exportCms, report).exportData(params); 443 report.println(Messages.get().container(Messages.RPT_EXPORT_MODULE_END_0), I_CmsReport.FORMAT_HEADLINE); 444 } 445 446 /** 447 * Returns the VFS resources to be exported additionally with the module.<p> 448 * 449 * @return the VFS resources to be exported additionally with the module 450 */ 451 public List<String> getAdditionalResources() { 452 453 return m_additionalResources; 454 } 455 456 /** 457 * @see org.opencms.importexport.I_CmsImportExportHandler#getDescription() 458 */ 459 public String getDescription() { 460 461 return m_description; 462 } 463 464 /** 465 * Returns the name of the export file in the real file system.<p> 466 * 467 * @return the name of the export file in the real file system 468 */ 469 public String getFileName() { 470 471 CmsMacroResolver resolver = new CmsMacroResolver(); 472 resolver.addMacro("version", OpenCms.getModuleManager().getModule(m_moduleName).getVersionStr()); 473 return resolver.resolveMacros(m_fileName); 474 } 475 476 /** 477 * Returns the import parameters.<p> 478 * 479 * @return the import parameters 480 */ 481 public CmsImportParameters getImportParameters() { 482 483 return m_importParams; 484 } 485 486 /** 487 * Returns the (package) name of the module to be exported.<p> 488 * 489 * @return the (package) name of the module to be exported 490 */ 491 public String getModuleName() { 492 493 return m_moduleName; 494 } 495 496 /** 497 * Returns the VFS resources to be exported additionally with the module as a list.<p> 498 * 499 * @return the VFS resources to be exported additionally with the module as a list 500 */ 501 public List<String> getResourcesAsList() { 502 503 return m_additionalResources; 504 } 505 506 /** 507 * @see org.opencms.importexport.I_CmsImportExportHandler#importData(CmsObject, I_CmsReport) 508 */ 509 public synchronized void importData(CmsObject cms, I_CmsReport report) 510 throws CmsXmlException, CmsImportExportException, CmsRoleViolationException, CmsException { 511 512 CmsImportParameters parameters = getImportParameters(); 513 CmsProject previousProject = cms.getRequestContext().getCurrentProject(); 514 try { 515 CmsProject importProject = null; 516 String modulePackageName = null; 517 String storedSiteRoot = cms.getRequestContext().getSiteRoot(); 518 CmsImportHelper helper = new CmsImportHelper(parameters); 519 try { 520 cms.getRequestContext().setSiteRoot("/"); 521 helper.openFile(); 522 modulePackageName = helper.getFileName(); 523 524 try { 525 // try to read a (leftover) module import project 526 importProject = cms.readProject( 527 Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 528 Messages.GUI_IMPORT_MODULE_PROJECT_NAME_1, 529 new Object[] {modulePackageName})); 530 } catch (CmsException e) { 531 // create a Project to import the module 532 importProject = cms.createProject( 533 Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 534 Messages.GUI_IMPORT_MODULE_PROJECT_NAME_1, 535 new Object[] {modulePackageName}), 536 Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 537 Messages.GUI_IMPORT_MODULE_PROJECT_DESC_1, 538 new Object[] {modulePackageName}), 539 OpenCms.getDefaultUsers().getGroupAdministrators(), 540 OpenCms.getDefaultUsers().getGroupAdministrators(), 541 CmsProject.PROJECT_TYPE_TEMPORARY); 542 } 543 544 cms.getRequestContext().setCurrentProject(importProject); 545 546 // copy the root folder to the project 547 cms.copyResourceToProject("/"); 548 } catch (Exception e) { 549 throw new CmsImportExportException( 550 Messages.get().container(Messages.ERR_IO_MODULE_IMPORT_1, parameters.getPath()), 551 e); 552 } finally { 553 helper.closeFile(); 554 cms.getRequestContext().setSiteRoot(storedSiteRoot); 555 } 556 557 reportBeginImport(report, modulePackageName); 558 importModule(cms, report, parameters); 559 report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 560 // now unlock and publish the project 561 cms.unlockProject(importProject.getUuid()); 562 OpenCms.getPublishManager().publishProject(cms, report); 563 OpenCms.getPublishManager().waitWhileRunning(); 564 565 report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_END_0), I_CmsReport.FORMAT_HEADLINE); 566 reportEndImport(report); 567 } finally { 568 cms.getRequestContext().setCurrentProject(previousProject); 569 } 570 } 571 572 /** 573 * @see org.opencms.importexport.I_CmsImportExportHandler#importData(org.opencms.file.CmsObject, java.lang.String, java.lang.String, org.opencms.report.I_CmsReport) 574 * 575 * @deprecated use {@link #importData(CmsObject, I_CmsReport)} instead 576 */ 577 @Deprecated 578 public void importData(CmsObject cms, String importFile, String importPath, I_CmsReport report) 579 throws CmsXmlException, CmsImportExportException, CmsRoleViolationException, CmsException { 580 581 CmsImportParameters parameters = new CmsImportParameters(importFile, importPath, true); 582 setImportParameters(parameters); 583 584 importData(cms, report); 585 } 586 587 /** 588 * @see org.opencms.importexport.I_CmsImportExportHandler#matches(org.dom4j.Document) 589 */ 590 public boolean matches(Document manifest) { 591 592 Element rootElement = manifest.getRootElement(); 593 594 return (rootElement.selectNodes("./module/name").size() > 0); 595 } 596 597 /** 598 * Sets the VFS resources to be exported additionally with the module.<p> 599 * 600 * @param resources the VFS resources to be exported additionally with the module 601 */ 602 public void setAdditionalResources(String[] resources) { 603 604 m_additionalResources = Arrays.asList(resources); 605 } 606 607 /** 608 * @see org.opencms.importexport.I_CmsImportExportHandler#setDescription(java.lang.String) 609 */ 610 public void setDescription(String description) { 611 612 m_description = description; 613 } 614 615 /** 616 * Sets the name of the export file in the real file system.<p> 617 * 618 * @param fileName the name of the export file in the real file system 619 */ 620 public void setFileName(String fileName) { 621 622 m_fileName = fileName; 623 } 624 625 /** 626 * Sets the import parameters.<p> 627 * 628 * @param importParams the parameters to set 629 */ 630 public void setImportParameters(CmsImportParameters importParams) { 631 632 m_importParams = importParams; 633 } 634 635 /** 636 * Will be called by the digester if a module was imported.<p> 637 * 638 * @param moduleHandler contains the imported module 639 */ 640 public void setModule(CmsModuleXmlHandler moduleHandler) { 641 642 m_importedModule = moduleHandler.getModule(); 643 } 644 645 /** 646 * Sets the (package) name of the module to be exported.<p> 647 * 648 * @param moduleName the (package) name of the module to be exported 649 */ 650 public void setModuleName(String moduleName) { 651 652 m_moduleName = moduleName; 653 } 654 655 /** 656 * Returns the module imported with the digester.<p> 657 * 658 * @return the module imported with the digester 659 */ 660 private CmsModule getModule() { 661 662 return m_importedModule; 663 } 664 665 /** 666 * Imports a module from an external file source.<p> 667 * 668 * @param cms must have been initialized with {@link CmsRole#DATABASE_MANAGER} permissions 669 * @param report the report to print the progress information to 670 * @param parameters the import parameters 671 * 672 * @return the imported module 673 * 674 * @throws CmsSecurityException if no {@link CmsRole#DATABASE_MANAGER} permissions are available 675 * @throws CmsConfigurationException if the module is already installed or the 676 * dependencies are not fulfilled 677 * @throws CmsException if errors occur reading the module data 678 */ 679 private synchronized CmsModule importModule(CmsObject cms, I_CmsReport report, CmsImportParameters parameters) 680 throws CmsSecurityException, CmsConfigurationException, CmsException { 681 682 // check if the user has the required permissions 683 OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER); 684 685 // read the module from the import file 686 CmsModule importedModule = readModuleFromImport(parameters.getPath()); 687 688 // check if the module is already installed 689 if (OpenCms.getModuleManager().hasModule(importedModule.getName())) { 690 throw new CmsConfigurationException( 691 Messages.get().container(Messages.ERR_MOD_ALREADY_INSTALLED_1, importedModule.getName())); 692 } 693 694 // check the module dependencies 695 List<CmsModuleDependency> dependencies = OpenCms.getModuleManager().checkDependencies( 696 importedModule, 697 CmsModuleManager.DEPENDENCY_MODE_IMPORT); 698 if (dependencies.size() > 0) { 699 // some dependencies not fulfilled 700 StringBuffer missingModules = new StringBuffer(); 701 for (CmsModuleDependency dependency : dependencies) { 702 missingModules.append(" ").append(dependency.getName()).append(", Version ").append( 703 dependency.getVersion()).append("\r\n"); 704 } 705 throw new CmsConfigurationException( 706 Messages.get().container( 707 Messages.ERR_MOD_DEPENDENCY_INFO_2, 708 importedModule.getName() + ", Version " + importedModule.getVersion(), 709 missingModules)); 710 } 711 712 // check the imported resource types for name / id conflicts 713 List<I_CmsResourceType> checkedTypes = new ArrayList<I_CmsResourceType>(); 714 for (I_CmsResourceType type : importedModule.getResourceTypes()) { 715 // first check against the already configured resource types 716 int externalConflictIndex = OpenCms.getResourceManager().getResourceTypes().indexOf(type); 717 if (externalConflictIndex >= 0) { 718 I_CmsResourceType conflictingType = OpenCms.getResourceManager().getResourceTypes().get( 719 externalConflictIndex); 720 if (!type.isIdentical(conflictingType)) { 721 // if name and id are identical, we assume this is a module replace operation 722 throw new CmsConfigurationException( 723 org.opencms.loader.Messages.get().container( 724 org.opencms.loader.Messages.ERR_CONFLICTING_MODULE_RESOURCE_TYPES_5, 725 new Object[] { 726 type.getTypeName(), 727 Integer.valueOf(type.getTypeId()), 728 importedModule.getName(), 729 conflictingType.getTypeName(), 730 Integer.valueOf(conflictingType.getTypeId())})); 731 } 732 } 733 // now check against the other resource types of the imported module 734 int internalConflictIndex = checkedTypes.indexOf(type); 735 if (internalConflictIndex >= 0) { 736 I_CmsResourceType conflictingType = checkedTypes.get(internalConflictIndex); 737 throw new CmsConfigurationException( 738 org.opencms.loader.Messages.get().container( 739 org.opencms.loader.Messages.ERR_CONFLICTING_RESTYPES_IN_MODULE_5, 740 new Object[] { 741 importedModule.getName(), 742 type.getTypeName(), 743 Integer.valueOf(type.getTypeId()), 744 conflictingType.getTypeName(), 745 Integer.valueOf(conflictingType.getTypeId())})); 746 } 747 // add the resource type for the next check 748 checkedTypes.add(type); 749 } 750 751 // import the module resources 752 CmsObject importCms = OpenCms.initCmsObject(cms); 753 String importSite = importedModule.getImportSite(); 754 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(importSite)) { 755 importCms.getRequestContext().setSiteRoot(importSite); 756 } else { 757 String siteToSet = importCms.getRequestContext().getSiteRoot(); 758 if ("".equals(siteToSet)) { 759 siteToSet = "/"; 760 } 761 importedModule.setSite(siteToSet); 762 } 763 764 // add the imported module to the module manager 765 OpenCms.getModuleManager().addModule(cms, importedModule); 766 767 // reinitialize the resource manager with additional module resource types if necessary 768 if (importedModule.getResourceTypes() != Collections.EMPTY_LIST) { 769 OpenCms.getResourceManager().initialize(cms); 770 } 771 // reinitialize the workplace manager with additional module explorer types if necessary 772 if (importedModule.getExplorerTypes() != Collections.EMPTY_LIST) { 773 OpenCms.getWorkplaceManager().addExplorerTypeSettings(importedModule); 774 } 775 776 CmsImport cmsImport = new CmsImport(importCms, report); 777 cmsImport.importData(parameters); 778 String importScript = importedModule.getImportScript(); 779 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(importScript)) { 780 LOG.info("Executing import script for module " + importedModule.getName()); 781 report.println(Messages.get().container(Messages.RPT_IMPORT_SCRIPT_HEADER_0), I_CmsReport.FORMAT_HEADLINE); 782 importScript = "echo on\n" + importScript; 783 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 784 PrintStream out = new PrintStream(buffer); 785 CmsShell shell = new CmsShell(cms, "${user}@${project}:${siteroot}|${uri}>", null, out, out); 786 shell.execute(importScript); 787 String outputString = buffer.toString(); 788 LOG.info("Shell output for import script was: \n" + outputString); 789 report.println(Messages.get().container(Messages.RPT_IMPORT_SCRIPT_OUTPUT_1, outputString)); 790 } 791 importedModule.setCheckpointTime(System.currentTimeMillis()); 792 OpenCms.getModuleManager().updateModuleConfiguration(); 793 return importedModule; 794 } 795}