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.main; 029 030import org.opencms.ade.configuration.CmsADEManager; 031import org.opencms.ade.containerpage.CmsContainerpageService; 032import org.opencms.cache.CmsVfsMemoryObjectCache; 033import org.opencms.configuration.CmsConfigurationException; 034import org.opencms.configuration.CmsConfigurationManager; 035import org.opencms.configuration.CmsImageCacheConfiguration; 036import org.opencms.configuration.CmsImportExportConfiguration; 037import org.opencms.configuration.CmsModuleConfiguration; 038import org.opencms.configuration.CmsParameterConfiguration; 039import org.opencms.configuration.CmsSchedulerConfiguration; 040import org.opencms.configuration.CmsSearchConfiguration; 041import org.opencms.configuration.CmsSitesConfiguration; 042import org.opencms.configuration.CmsSystemConfiguration; 043import org.opencms.configuration.CmsVariablesConfiguration; 044import org.opencms.configuration.CmsVfsConfiguration; 045import org.opencms.configuration.CmsWorkplaceConfiguration; 046import org.opencms.configuration.I_CmsNeedsAdminCmsObject; 047import org.opencms.crypto.I_CmsTextEncryption; 048import org.opencms.db.CmsAliasManager; 049import org.opencms.db.CmsDbEntryNotFoundException; 050import org.opencms.db.CmsDefaultUsers; 051import org.opencms.db.CmsExportPoint; 052import org.opencms.db.CmsLoginManager; 053import org.opencms.db.CmsModificationContext; 054import org.opencms.db.CmsSecurityManager; 055import org.opencms.db.CmsSqlManager; 056import org.opencms.db.CmsSubscriptionManager; 057import org.opencms.db.timing.CmsDefaultProfilingHandler; 058import org.opencms.db.timing.CmsThreadStatsTreeProfilingHandler; 059import org.opencms.file.CmsObject; 060import org.opencms.file.CmsProject; 061import org.opencms.file.CmsProperty; 062import org.opencms.file.CmsPropertyDefinition; 063import org.opencms.file.CmsRequestContext; 064import org.opencms.file.CmsResource; 065import org.opencms.file.CmsResourceFilter; 066import org.opencms.file.CmsUser; 067import org.opencms.file.CmsVfsResourceNotFoundException; 068import org.opencms.file.quota.CmsFolderSizeTracker; 069import org.opencms.flex.CmsFlexCache; 070import org.opencms.flex.CmsFlexCacheConfiguration; 071import org.opencms.flex.CmsFlexController; 072import org.opencms.gwt.CmsGwtService; 073import org.opencms.gwt.CmsGwtServiceContext2; 074import org.opencms.gwt.shared.CmsGwtConstants; 075import org.opencms.i18n.CmsEncoder; 076import org.opencms.i18n.CmsI18nInfo; 077import org.opencms.i18n.CmsLocaleManager; 078import org.opencms.i18n.CmsMessageContainer; 079import org.opencms.i18n.CmsSingleTreeLocaleHandler; 080import org.opencms.i18n.CmsVfsBundleManager; 081import org.opencms.importexport.CmsImportExportManager; 082import org.opencms.json.JSONObject; 083import org.opencms.jsp.CmsDefaultElementMarker; 084import org.opencms.jsp.I_CmsElementMarker; 085import org.opencms.jsp.jsonpart.CmsJsonPartFilter; 086import org.opencms.jsp.userdata.CmsUserDataRequestManager; 087import org.opencms.jsp.util.CmsJspStandardContextBean; 088import org.opencms.letsencrypt.CmsLetsEncryptConfiguration; 089import org.opencms.loader.CmsImageLoader; 090import org.opencms.loader.CmsJspLoader; 091import org.opencms.loader.CmsResourceManager; 092import org.opencms.loader.CmsTemplateContextManager; 093import org.opencms.loader.I_CmsFlexCacheEnabledLoader; 094import org.opencms.loader.I_CmsResourceLoader; 095import org.opencms.lock.CmsLockManager; 096import org.opencms.module.CmsModuleManager; 097import org.opencms.monitor.CmsMemoryMonitor; 098import org.opencms.monitor.CmsMemoryMonitorConfiguration; 099import org.opencms.mx.CmsDiagnosticsMXBean; 100import org.opencms.publish.CmsPublishEngine; 101import org.opencms.publish.CmsPublishManager; 102import org.opencms.repository.CmsRepositoryManager; 103import org.opencms.rmi.CmsRemoteShellServer; 104import org.opencms.scheduler.CmsScheduleManager; 105import org.opencms.search.CmsSearchManager; 106import org.opencms.security.CmsOrgUnitManager; 107import org.opencms.security.CmsPersistentLoginTokenHandler; 108import org.opencms.security.CmsRole; 109import org.opencms.security.CmsRoleManager; 110import org.opencms.security.CmsRoleViolationException; 111import org.opencms.security.CmsSecurityException; 112import org.opencms.security.I_CmsAuthorizationHandler; 113import org.opencms.security.I_CmsCredentialsResolver; 114import org.opencms.security.I_CmsPasswordHandler; 115import org.opencms.security.I_CmsSecretStore; 116import org.opencms.security.I_CmsValidationHandler; 117import org.opencms.security.twofactor.CmsTwoFactorAuthenticationHandler; 118import org.opencms.site.CmsSite; 119import org.opencms.site.CmsSiteManagerImpl; 120import org.opencms.site.CmsSiteMatcher; 121import org.opencms.staticexport.CmsDefaultLinkSubstitutionHandler; 122import org.opencms.staticexport.CmsLinkManager; 123import org.opencms.staticexport.CmsStaticExportManager; 124import org.opencms.ugc.CmsUgcSessionFactory; 125import org.opencms.ui.apps.CmsWorkplaceAppManager; 126import org.opencms.ui.dialogs.CmsPublishScheduledDialog; 127import org.opencms.ui.error.CmsErrorUI; 128import org.opencms.ui.login.CmsLoginHelper; 129import org.opencms.ui.login.CmsLoginUI; 130import org.opencms.util.CmsRequestUtil; 131import org.opencms.util.CmsStringUtil; 132import org.opencms.util.CmsTaskWatcher; 133import org.opencms.util.CmsUUID; 134import org.opencms.workflow.CmsDefaultWorkflowManager; 135import org.opencms.workflow.I_CmsWorkflowManager; 136import org.opencms.workplace.CmsWorkplace; 137import org.opencms.workplace.CmsWorkplaceLoginHandler; 138import org.opencms.workplace.CmsWorkplaceManager; 139import org.opencms.workplace.CmsWorkplaceSettings; 140import org.opencms.xml.CmsXmlContentTypeManager; 141import org.opencms.xml.CmsXmlUtils; 142import org.opencms.xml.containerpage.CmsFormatterConfiguration; 143import org.opencms.xml.xml2json.I_CmsApiAuthorizationHandler; 144 145import java.io.FileOutputStream; 146import java.io.IOException; 147import java.security.Security; 148import java.util.ArrayList; 149import java.util.Collections; 150import java.util.Date; 151import java.util.HashMap; 152import java.util.HashSet; 153import java.util.Hashtable; 154import java.util.Iterator; 155import java.util.LinkedHashMap; 156import java.util.List; 157import java.util.Locale; 158import java.util.Map; 159import java.util.ServiceLoader; 160import java.util.Set; 161import java.util.concurrent.CopyOnWriteArrayList; 162import java.util.concurrent.Future; 163import java.util.concurrent.ScheduledThreadPoolExecutor; 164import java.util.concurrent.TimeUnit; 165 166import org.apache.commons.logging.Log; 167import org.apache.logging.log4j.CloseableThreadContext; 168import org.apache.logging.log4j.jul.Log4jBridgeHandler; 169 170import org.antlr.stringtemplate.StringTemplate; 171 172import com.google.common.base.Optional; 173import com.google.common.util.concurrent.ThreadFactoryBuilder; 174 175import jakarta.servlet.ServletConfig; 176import jakarta.servlet.ServletContext; 177import jakarta.servlet.ServletException; 178import jakarta.servlet.http.HttpServletRequest; 179import jakarta.servlet.http.HttpServletResponse; 180import jakarta.servlet.http.HttpSession; 181 182/** 183 * The internal implementation of the core OpenCms "operating system" functions.<p> 184 * 185 * All access to this class must be done through the public static methods 186 * of the <code>{@link org.opencms.main.OpenCms}</code> object. 187 * Under no circumstances should you ever try to access this class directly.<p> 188 * 189 * This class is so OpenCms internal you should not even be reading this documentation ;-)<p> 190 * 191 * Any request to the <code>{@link org.opencms.main.OpenCmsServlet}</code> will be forwarded to this core class. 192 * The core will then try to map the request to a VFS (Virtual File System) URI, 193 * that is a <code>{@link org.opencms.file.CmsResource}</code> in the OpenCms database. 194 * If a resource is found, it will be read and forwarded to 195 * to the corresponding <code>{@link org.opencms.loader.I_CmsResourceLoader}</code>, 196 * which will then generate the output for the requested resource and return it to the requesting client.<p> 197 * 198 * There will be only one singleton instance of this object created for 199 * this core class. This means that in the default configuration, where 200 * OpenCms is accessed through a servlet context, there will be only one instance of 201 * the core in that servlet context.<p> 202 * 203 * @since 6.0.0 204 */ 205public final class OpenCmsCore { 206 207 static { 208 Log4jBridgeHandler.install(true, null, true); 209 } 210 211 /** Parameter to control whether generated links should always include the host. */ 212 public static final String PARAM_FORCE_ABSOLUTE_LINKS = "__forceAbsoluteLinks"; 213 214 /** The static log object for this class. */ 215 static final Log LOG = CmsLog.getLog(OpenCmsCore.class); 216 217 /** Lock object for synchronization. */ 218 private static final Object LOCK = new Object(); 219 220 /** Indicates if the configuration was successfully finished or not. */ 221 private static CmsMessageContainer m_errorCondition; 222 223 /** One instance to rule them all, one instance to find them... */ 224 private static OpenCmsCore m_instance; 225 226 static { 227 final String keyEntityExpansionLimit = "jdk.xml.entityExpansionLimit"; 228 if (System.getProperty(keyEntityExpansionLimit) == null) { 229 System.setProperty(keyEntityExpansionLimit, "64000"); 230 } 231 } 232 233 /** The ADE manager instance. */ 234 private CmsADEManager m_adeManager; 235 236 /** The manager for page aliases. */ 237 private CmsAliasManager m_aliasManager; 238 239 /** Map of API authorization handlers, with their names as keys. */ 240 private Map<String, I_CmsApiAuthorizationHandler> m_apiAuthorizations; 241 242 /** The configured authorization handler. */ 243 private I_CmsAuthorizationHandler m_authorizationHandler; 244 245 /** Admin CMS object. */ 246 private CmsObject m_configAdminCms; 247 248 /** The configuration manager that contains the information from the XML configuration. */ 249 private CmsConfigurationManager m_configurationManager; 250 251 /** The object used for resolving database user credentials. */ 252 private I_CmsCredentialsResolver m_credentialsResolver; 253 254 /** List of configured directory default file names. */ 255 private List<String> m_defaultFiles; 256 257 /** The default user and group names. */ 258 private CmsDefaultUsers m_defaultUsers; 259 260 /** The event manager for the event handling. */ 261 private CmsEventManager m_eventManager; 262 263 /** The thread pool executor. */ 264 private ScheduledThreadPoolExecutor m_executor; 265 266 /** The set of configured export points. */ 267 private Set<CmsExportPoint> m_exportPoints; 268 269 /** The flex cache instance. */ 270 private CmsFlexCache m_flexCache; 271 272 /** The context objects for GWT services. */ 273 private Map<String, CmsGwtServiceContext2> m_gwtServiceContexts; 274 275 /** The site manager contains information about the Cms import/export. */ 276 private CmsImportExportManager m_importExportManager; 277 278 /** The LetsEncrypt configuration. */ 279 private CmsLetsEncryptConfiguration m_letsEncryptConfig; 280 281 /** The link manager to resolve links in <cms:link> tags. */ 282 private CmsLinkManager m_linkManager; 283 284 /** The locale manager used for obtaining the current locale. */ 285 private CmsLocaleManager m_localeManager; 286 287 /** The login manager. */ 288 private CmsLoginManager m_loginManager; 289 290 /** The memory monitor for the collection of memory and runtime statistics. */ 291 private CmsMemoryMonitor m_memoryMonitor; 292 293 /** The module manager. */ 294 private CmsModuleManager m_moduleManager; 295 296 /** The organizational unit manager. */ 297 private CmsOrgUnitManager m_orgUnitManager; 298 299 /** The password handler used to digest and validate passwords. */ 300 private I_CmsPasswordHandler m_passwordHandler; 301 302 /** The publish engine. */ 303 private CmsPublishEngine m_publishEngine; 304 305 /** The publish manager instance. */ 306 private CmsPublishManager m_publishManager; 307 308 /** The remote shell server. */ 309 private CmsRemoteShellServer m_remoteShellServer; 310 311 /** The repository manager. */ 312 private CmsRepositoryManager m_repositoryManager; 313 314 /** The configured request handlers that handle "special" requests, for example in the static export on demand. */ 315 private Map<String, I_CmsRequestHandler> m_requestHandlers; 316 317 /** Stores the resource init handlers that allow modification of the requested resource. */ 318 private List<I_CmsResourceInit> m_resourceInitHandlers; 319 320 /** The resource manager. */ 321 private CmsResourceManager m_resourceManager; 322 323 /** The role manager. */ 324 private CmsRoleManager m_roleManager; 325 326 /** The runlevel of this OpenCmsCore object instance. */ 327 private int m_runLevel; 328 329 /** The runtime properties allow storage of system wide accessible runtime information. */ 330 private Map<Object, Object> m_runtimeProperties; 331 332 /** The configured scheduler manager. */ 333 private CmsScheduleManager m_scheduleManager; 334 335 /** The search manager provides indexing and searching. */ 336 private CmsSearchManager m_searchManager; 337 338 /** The security manager to access the database and validate user permissions. */ 339 private CmsSecurityManager m_securityManager; 340 341 /** The session manager. */ 342 private CmsSessionManager m_sessionManager; 343 344 /** The site manager contains information about all configured sites. */ 345 private CmsSiteManagerImpl m_siteManager; 346 347 /** List of start/stop handlers. */ 348 private List<I_CmsStartStopHandler> m_startStopHandlers = new ArrayList<>(); 349 350 /** The static export manager. */ 351 private CmsStaticExportManager m_staticExportManager; 352 353 /** The subscription manager. */ 354 private CmsSubscriptionManager m_subscriptionManager; 355 356 /** The system information container for "read only" system settings. */ 357 private CmsSystemInfo m_systemInfo; 358 359 /** The template context manager. */ 360 private CmsTemplateContextManager m_templateContextManager; 361 362 /** The text encryptions. */ 363 private LinkedHashMap<String, I_CmsTextEncryption> m_textEncryptions; 364 365 /** The thread store. */ 366 private CmsThreadStore m_threadStore; 367 368 /** The 2FA handler. */ 369 private CmsTwoFactorAuthenticationHandler m_twoFactorAuthenticationHandler; 370 371 /** The user data request manager. */ 372 private CmsUserDataRequestManager m_userDataRequestManager; 373 374 /** The runtime validation handler. */ 375 private I_CmsValidationHandler m_validationHandler; 376 377 /** The VFS bundle manager. */ 378 private CmsVfsBundleManager m_vfsBundleManager; 379 380 /** The default memory object cache instance. */ 381 private CmsVfsMemoryObjectCache m_vfsMemoryObjectCache; 382 383 /** The workflow manager instance. */ 384 private I_CmsWorkflowManager m_workflowManager; 385 386 /** The workplace app manager. */ 387 private CmsWorkplaceAppManager m_workplaceAppManager; 388 389 /** The workplace manager contains information about the global workplace settings. */ 390 private CmsWorkplaceManager m_workplaceManager; 391 392 /** The XML content type manager that contains the initialized XML content types. */ 393 private CmsXmlContentTypeManager m_xmlContentTypeManager; 394 395 /** The future for the offline folder size tracker. */ 396 private Future<CmsFolderSizeTracker> m_folderSizeTrackerFuture; 397 398 /** The future for the online folder size tracker. */ 399 private Future<CmsFolderSizeTracker> m_onlineFolderSizeTrackerFuture; 400 401 private List<Runnable> m_shutdownActions = new CopyOnWriteArrayList<Runnable>(); 402 403 /** The configured secret store. */ 404 private I_CmsSecretStore m_secretStore; 405 406 /** The configured element marker handler (no-op default until configured). */ 407 private I_CmsElementMarker m_elementMarker = new CmsDefaultElementMarker(); 408 409 /** 410 * Protected constructor that will initialize the singleton OpenCms instance 411 * with runlevel {@link OpenCms#RUNLEVEL_1_CORE_OBJECT}.<p> 412 * 413 * @throws CmsInitException in case of errors during the initialization 414 */ 415 private OpenCmsCore() 416 throws CmsInitException { 417 418 if ((m_instance != null) && (m_instance.getRunLevel() > OpenCms.RUNLEVEL_0_OFFLINE)) { 419 throw new CmsInitException(Messages.get().container(Messages.ERR_ALREADY_INITIALIZED_0)); 420 } 421 initMembers(); 422 m_instance = this; 423 setRunLevel(OpenCms.RUNLEVEL_1_CORE_OBJECT); 424 } 425 426 /** 427 * Returns the path for the request.<p> 428 * 429 * First checks the {@link HttpServletRequest#getPathInfo()}, then 430 * the configured request error page attribute (if set), and then 431 * if still undefined the <code>/</code> is returned as path info.<p> 432 * 433 * This is only needed when the {@link HttpServletRequest#getPathInfo()} 434 * is not really working as expected like in BEA WLS 9.x, where we have 435 * to use the 'weblogic.servlet.errorPage' request attribute.<p> 436 * 437 * @param req the http request context 438 * 439 * @return the path for the request 440 */ 441 public static String getPathInfo(HttpServletRequest req) { 442 443 String path = req.getPathInfo(); 444 if (path == null) { 445 // if the HttpServletRequest#getPathInfo() method does not work properly 446 String requestErrorPageAttribute = OpenCms.getSystemInfo().getServletContainerSettings().getRequestErrorPageAttribute(); 447 if (requestErrorPageAttribute != null) { 448 // use the proper page attribute 449 path = (String)req.getAttribute(requestErrorPageAttribute); 450 if (path != null) { 451 int pos = path.indexOf("/", 1); 452 if (pos > 0) { 453 // cut off the servlet name 454 path = path.substring(pos); 455 } 456 } 457 } 458 } 459 if (path == null) { 460 path = "/"; 461 } 462 return path; 463 } 464 465 /** 466 * Returns the initialized OpenCms singleton instance.<p> 467 * 468 * @return the initialized OpenCms singleton instance 469 */ 470 protected static OpenCmsCore getInstance() { 471 472 if (m_errorCondition != null) { 473 // OpenCms is not properly initialized 474 throw new CmsInitException(m_errorCondition, false); 475 } 476 477 if (m_instance != null) { 478 return m_instance; 479 } 480 synchronized (LOCK) { 481 if (m_instance == null) { 482 try { 483 // create a new core object with runlevel 1 484 m_instance = new OpenCmsCore(); 485 } catch (CmsInitException e) { 486 // already initialized, this is all we need 487 LOG.debug(e.getMessage(), e); 488 } 489 } 490 } 491 return m_instance; 492 } 493 494 /** 495 * Sets the error condition.<p> 496 * 497 * @param errorCondition the error condition to set 498 */ 499 protected static void setErrorCondition(CmsMessageContainer errorCondition) { 500 501 // init exceptions should only be thrown during setup process 502 if ((m_instance != null) && (m_instance.getRunLevel() < OpenCms.RUNLEVEL_3_SHELL_ACCESS)) { 503 if (!Messages.ERR_CRITICAL_INIT_WIZARD_0.equals(errorCondition.getKey())) { 504 // if wizard is still enabled allow retry of initialization (for setup wizard) 505 m_errorCondition = errorCondition; 506 // output an error message to the console 507 System.err.println( 508 Messages.get().getBundle().key(Messages.LOG_INIT_FAILURE_MESSAGE_1, errorCondition.key())); 509 } 510 LOG.error(errorCondition.key(), new CmsException(errorCondition)); 511 m_instance = null; 512 } else if (m_instance != null) { 513 // OpenCms already was successful initialized 514 LOG.warn( 515 Messages.get().getBundle().key( 516 Messages.LOG_INIT_INVALID_ERROR_2, 517 Integer.valueOf(m_instance.getRunLevel()), 518 errorCondition.key())); 519 } 520 } 521 522 /** 523 * Gets the default CmsVfsMemoryCache instance. 524 * 525 * @return the default cache instance 526 */ 527 public CmsVfsMemoryObjectCache getVfsMemoryObjectCache() { 528 529 if (m_vfsMemoryObjectCache == null) { 530 m_vfsMemoryObjectCache = new CmsVfsMemoryObjectCache(); 531 } 532 return m_vfsMemoryObjectCache; 533 534 } 535 536 /** 537 * Registers a callback to be called before shutdown. 538 * 539 * @param action the action to execute before shutdown 540 */ 541 public void registerShutdownAction(Runnable action) { 542 543 m_shutdownActions.add(action); 544 } 545 546 /** 547 * Adds the specified request handler to the Map of OpenCms request handlers. <p> 548 * 549 * @param handler the handler to add 550 */ 551 protected void addRequestHandler(I_CmsRequestHandler handler) { 552 553 if (handler == null) { 554 return; 555 } 556 String[] names = handler.getHandlerNames(); 557 for (int i = 0; i < names.length; i++) { 558 String name = names[i]; 559 if (m_requestHandlers.get(name) != null) { 560 CmsLog.INIT.error(Messages.get().getBundle().key(Messages.LOG_DUPLICATE_REQUEST_HANDLER_1, name)); 561 continue; 562 } 563 m_requestHandlers.put(name, handler); 564 if (CmsLog.INIT.isInfoEnabled()) { 565 CmsLog.INIT.info( 566 Messages.get().getBundle().key( 567 Messages.INIT_ADDED_REQUEST_HANDLER_2, 568 name, 569 handler.getClass().getName())); 570 } 571 } 572 } 573 574 /** 575 * Gets the ADE manager, and makes sure it is initialized.<p> 576 * 577 * @return the initialized ADE manager 578 */ 579 protected CmsADEManager getADEManager() { 580 581 if (!m_adeManager.isInitialized()) { 582 m_adeManager.initialize(); 583 } 584 return m_adeManager; 585 } 586 587 /** 588 * Returns the alias manager.<p> 589 * 590 * @return the alias manager 591 */ 592 protected CmsAliasManager getAliasManager() { 593 594 return m_aliasManager; 595 } 596 597 /** 598 * Gets the API authorization handler with the given name, or null if it doesn't exist. 599 * 600 * @param name the name of the API authorization handler 601 * @return the API authorization handler, or null if it wasn't found 602 */ 603 protected I_CmsApiAuthorizationHandler getApiAuthorization(String name) { 604 605 return m_apiAuthorizations.get(name); 606 607 } 608 609 /** 610 * Returns the configured authorization handler.<p> 611 * 612 * @return the configured authorization handler 613 */ 614 protected I_CmsAuthorizationHandler getAuthorizationHandler() { 615 616 return m_authorizationHandler; 617 } 618 619 /** 620 * Returns the initialized OpenCms configuration manager.<p> 621 * 622 * @return the initialized OpenCms configuration manager 623 */ 624 protected CmsConfigurationManager getConfigurationManager() { 625 626 return m_configurationManager; 627 } 628 629 /** 630 * Gets the configured credentials resolver instance.<p> 631 * 632 * @return the credentials resolver 633 */ 634 protected I_CmsCredentialsResolver getCredentialsResolver() { 635 636 if (m_credentialsResolver == null) { 637 CmsSystemConfiguration systemConfig = (CmsSystemConfiguration)m_configurationManager.getConfiguration( 638 CmsSystemConfiguration.class); 639 return systemConfig.getCredentialsResolver(); 640 } 641 642 return m_credentialsResolver; 643 } 644 645 /** 646 * Gets the database pool names.<p> 647 * 648 * @return the configured database pool names 649 */ 650 protected List<String> getDbPoolNames() { 651 652 return new ArrayList<>(m_configurationManager.getConfiguration().getList("db.pools")); 653 654 } 655 656 /** 657 * Returns the configured list of default directory file names.<p> 658 * 659 * @return the configured list of default directory file names 660 */ 661 protected List<String> getDefaultFiles() { 662 663 return m_defaultFiles; 664 } 665 666 /** 667 * Returns the default user and group name configuration.<p> 668 * 669 * @return the default user and group name configuration 670 */ 671 protected CmsDefaultUsers getDefaultUsers() { 672 673 return m_defaultUsers; 674 } 675 676 /** 677 * Gets the configured element marker handler (a no-op default when none is configured). 678 * 679 * @return the element marker handler (never <code>null</code>) 680 */ 681 protected I_CmsElementMarker getElementMarker() { 682 683 return m_elementMarker; 684 } 685 686 /** 687 * Returns the OpenCms event manager.<p> 688 * 689 * @return the OpenCms event manager 690 */ 691 protected CmsEventManager getEventManager() { 692 693 return m_eventManager; 694 } 695 696 /** 697 * Gets the thread pool executor.<p> 698 * 699 * @return the thread pool executor 700 */ 701 protected ScheduledThreadPoolExecutor getExecutor() { 702 703 return m_executor; 704 } 705 706 /** 707 * Returns the configured export points, 708 * the returned set being an unmodifiable set.<p> 709 * 710 * @return an unmodifiable set of the configured export points 711 */ 712 protected Set<CmsExportPoint> getExportPoints() { 713 714 return m_exportPoints; 715 } 716 717 /** 718 * Gets the flex cache. 719 * @return CmsFlexCache 720 */ 721 722 protected CmsFlexCache getFlexCache() { 723 724 return m_flexCache; 725 } 726 727 /** 728 * Gets a string containing all keys and variations currently in the flex cache, for debug purposes.<p> 729 * 730 * @return a debug information string with the flex cache data 731 */ 732 protected String getFlexCacheKeyDump() { 733 734 if (m_flexCache != null) { 735 StringBuffer buffer = new StringBuffer(); 736 m_flexCache.dumpKeys(buffer); 737 return buffer.toString(); 738 } else { 739 return null; 740 } 741 } 742 743 /** 744 * Gets the folder size tracker for the Online or Offline project 745 * @return true to get the online folder size tracker, false for the offline one 746 */ 747 protected CmsFolderSizeTracker getFolderSizeTracker(boolean online) { 748 749 try { 750 return online ? m_onlineFolderSizeTrackerFuture.get() : m_folderSizeTrackerFuture.get(); 751 } catch (Exception e) { 752 LOG.error(e.getLocalizedMessage(), e); 753 return null; 754 } 755 } 756 757 /** 758 * Returns the central image cache retention and maintenance configuration.<p> 759 * 760 * @return the image cache configuration 761 */ 762 protected CmsImageCacheConfiguration getImageCacheConfiguration() { 763 764 CmsSystemConfiguration systemConfig = (CmsSystemConfiguration)m_configurationManager.getConfiguration( 765 CmsSystemConfiguration.class); 766 return systemConfig.getImageCacheConfiguration(); 767 } 768 769 /** 770 * Returns the initialized import/export manager, 771 * which contains information about the Cms import/export.<p> 772 * 773 * @return the initialized import/export manager 774 */ 775 protected CmsImportExportManager getImportExportManager() { 776 777 return m_importExportManager; 778 } 779 780 /** 781 * Gets the LetsEncrypt configuration.<p> 782 * 783 * @return the LetsEncrypt configuration 784 */ 785 protected CmsLetsEncryptConfiguration getLetsEncryptConfig() { 786 787 return m_letsEncryptConfig; 788 } 789 790 /** 791 * Returns the link manager to resolve links in <link> tags.<p> 792 * 793 * @return the link manager to resolve links in <link> tags 794 */ 795 protected CmsLinkManager getLinkManager() { 796 797 return m_linkManager; 798 } 799 800 /** 801 * Returns the locale manager used for obtaining the current locale.<p> 802 * 803 * @return the locale manager 804 */ 805 protected CmsLocaleManager getLocaleManager() { 806 807 return m_localeManager; 808 } 809 810 /** 811 * Returns the lock manager used for the locking mechanism.<p> 812 * 813 * @return the lock manager used for the locking mechanism 814 */ 815 protected CmsLockManager getLockManager() { 816 817 return m_securityManager.getLockManager(); 818 } 819 820 /** 821 * Returns the login manager used to check the validity of a login.<p> 822 * 823 * @return the login manager 824 */ 825 protected CmsLoginManager getLoginManager() { 826 827 return m_loginManager; 828 } 829 830 /** 831 * Returns the memory monitor.<p> 832 * 833 * @return the memory monitor 834 */ 835 protected CmsMemoryMonitor getMemoryMonitor() { 836 837 return m_memoryMonitor; 838 } 839 840 /** 841 * Returns the module manager.<p> 842 * 843 * @return the module manager 844 */ 845 protected CmsModuleManager getModuleManager() { 846 847 return m_moduleManager; 848 } 849 850 /** 851 * Returns the organizational unit manager.<p> 852 * 853 * @return the organizational unit manager 854 */ 855 protected CmsOrgUnitManager getOrgUnitManager() { 856 857 return m_orgUnitManager; 858 } 859 860 /** 861 * Return the password handler.<p> 862 * 863 * @return the password handler 864 */ 865 protected I_CmsPasswordHandler getPasswordHandler() { 866 867 return m_passwordHandler; 868 } 869 870 /** 871 * Returns the publish manager instance.<p> 872 * 873 * @return the publish manager instance 874 */ 875 protected CmsPublishManager getPublishManager() { 876 877 return m_publishManager; 878 } 879 880 /** 881 * Returns the repository manager.<p> 882 * 883 * @return the repository manager 884 */ 885 protected CmsRepositoryManager getRepositoryManager() { 886 887 return m_repositoryManager; 888 } 889 890 /** 891 * Returns the handler instance for the specified name, 892 * or null if the name does not match any handler name.<p> 893 * 894 * @param name the name of the handler instance to return 895 * @return the handler instance for the specified name 896 */ 897 protected I_CmsRequestHandler getRequestHandler(String name) { 898 899 return m_requestHandlers.get(name); 900 } 901 902 /** 903 * Returns the resource manager.<p> 904 * 905 * @return the resource manager 906 */ 907 protected CmsResourceManager getResourceManager() { 908 909 return m_resourceManager; 910 } 911 912 /** 913 * Returns the role manager.<p> 914 * 915 * @return the role manager 916 */ 917 protected CmsRoleManager getRoleManager() { 918 919 return m_roleManager; 920 } 921 922 /** 923 * Returns the runlevel of this OpenCmsCore object instance.<p> 924 * 925 * For a detailed description about the possible run levels, 926 * please see {@link OpenCms#getRunLevel()}.<p> 927 * 928 * @return the runlevel of this OpenCmsCore object instance 929 * 930 * @see OpenCms#getRunLevel() 931 */ 932 protected int getRunLevel() { 933 934 return m_runLevel; 935 } 936 937 /** 938 * Looks up a value in the runtime property Map.<p> 939 * 940 * @param key the key to look up in the runtime properties 941 * @return the value for the key, or null if the key was not found 942 */ 943 protected Object getRuntimeProperty(Object key) { 944 945 return m_runtimeProperties.get(key); 946 } 947 948 /** 949 * Returns the configured schedule manager.<p> 950 * 951 * @return the configured schedule manager 952 */ 953 protected CmsScheduleManager getScheduleManager() { 954 955 return m_scheduleManager; 956 } 957 958 /** 959 * Returns the initialized search manager, 960 * which provides indexing and searching operations.<p> 961 * 962 * @return the initialized search manager 963 */ 964 protected CmsSearchManager getSearchManager() { 965 966 return m_searchManager; 967 } 968 969 /** 970 * Gets the secret store. 971 * 972 * @return the secret store 973 */ 974 protected I_CmsSecretStore getSecretStore() { 975 976 return m_secretStore; 977 } 978 979 /** 980 * Returns the initialized OpenCms security manager.<p> 981 * 982 * @return the initialized OpenCms security manager 983 */ 984 protected CmsSecurityManager getSecurityManager() { 985 986 return m_securityManager; 987 } 988 989 /** 990 * Returns the session manager.<p> 991 * 992 * @return the session manager 993 */ 994 protected CmsSessionManager getSessionManager() { 995 996 return m_sessionManager; 997 } 998 999 /** 1000 * Returns the initialized site manager, 1001 * which contains information about all configured sites.<p> 1002 * 1003 * @return the initialized site manager 1004 */ 1005 protected CmsSiteManagerImpl getSiteManager() { 1006 1007 return m_siteManager; 1008 } 1009 1010 /** 1011 * Returns an instance of the common sql manager.<p> 1012 * 1013 * @return an instance of the common sql manager 1014 */ 1015 protected CmsSqlManager getSqlManager() { 1016 1017 return m_securityManager.getSqlManager(); 1018 } 1019 1020 /** 1021 * Returns the properties for the static export.<p> 1022 * 1023 * @return the properties for the static export 1024 */ 1025 protected CmsStaticExportManager getStaticExportManager() { 1026 1027 return m_staticExportManager; 1028 } 1029 1030 /** 1031 * Returns the subscription manager.<p> 1032 * 1033 * @return the subscription manager 1034 */ 1035 protected CmsSubscriptionManager getSubscriptionManager() { 1036 1037 return m_subscriptionManager; 1038 } 1039 1040 /** 1041 * Returns the system information storage.<p> 1042 * 1043 * @return the system information storage 1044 */ 1045 protected CmsSystemInfo getSystemInfo() { 1046 1047 return m_systemInfo; 1048 } 1049 1050 /** 1051 * Gets the template context manager instance.<p> 1052 * 1053 * @return the template context manager instance 1054 */ 1055 protected CmsTemplateContextManager getTemplateContextManager() { 1056 1057 return m_templateContextManager; 1058 1059 } 1060 1061 /** 1062 * Gets the text encryptions. 1063 * 1064 * @return the text encryptions 1065 */ 1066 protected Map<String, I_CmsTextEncryption> getTextEncryptions() { 1067 1068 return m_textEncryptions; 1069 } 1070 1071 /** 1072 * Returns the OpenCms Thread store.<p> 1073 * 1074 * @return the OpenCms Thread store 1075 */ 1076 protected CmsThreadStore getThreadStore() { 1077 1078 return m_threadStore; 1079 } 1080 1081 /** 1082 * Gets the two-factor authentication handler. 1083 * 1084 * @return the two-factor authentication handler 1085 */ 1086 protected CmsTwoFactorAuthenticationHandler getTwoFactorAuthenticationHandler() { 1087 1088 return m_twoFactorAuthenticationHandler; 1089 } 1090 1091 /** 1092 * Gets the user data request manager. 1093 * 1094 * @return the user data request manager 1095 */ 1096 protected CmsUserDataRequestManager getUserDataRequestManager() { 1097 1098 return m_userDataRequestManager; 1099 } 1100 1101 /** 1102 * Returns the runtime validation handler.<p> 1103 * 1104 * @return the validation handler 1105 */ 1106 protected I_CmsValidationHandler getValidationHandler() { 1107 1108 return m_validationHandler; 1109 } 1110 1111 /** 1112 * Returns the workflow manager instance.<p> 1113 * 1114 * @return the workflow manager 1115 */ 1116 protected I_CmsWorkflowManager getWorkflowManager() { 1117 1118 return m_workflowManager; 1119 } 1120 1121 /** 1122 * Returns the workplace app manager.<p> 1123 * 1124 * @return the workplace app manager 1125 */ 1126 protected CmsWorkplaceAppManager getWorkplaceAppManager() { 1127 1128 return m_workplaceAppManager; 1129 } 1130 1131 /** 1132 * Returns the initialized workplace manager, 1133 * which contains information about the global workplace settings.<p> 1134 * 1135 * @return the initialized workplace manager 1136 */ 1137 protected CmsWorkplaceManager getWorkplaceManager() { 1138 1139 return m_workplaceManager; 1140 } 1141 1142 /** 1143 * Returns the XML content type manager.<p> 1144 * 1145 * @return the XML content type manager 1146 */ 1147 protected CmsXmlContentTypeManager getXmlContentTypeManager() { 1148 1149 if (m_xmlContentTypeManager != null) { 1150 return m_xmlContentTypeManager; 1151 } 1152 if (getRunLevel() == OpenCms.RUNLEVEL_1_CORE_OBJECT) { 1153 // this is only to enable test cases to run 1154 m_xmlContentTypeManager = CmsXmlContentTypeManager.createTypeManagerForTestCases(); 1155 } 1156 return m_xmlContentTypeManager; 1157 } 1158 1159 /** 1160 * Initializes the OpenCms context for Vaadin UI servlet.<p> 1161 * 1162 * @param req the request 1163 * @param res the response 1164 * @param servlet the UI servlet 1165 * 1166 * @throws IOException if user authentication fails 1167 * @throws CmsException if something goes wrong 1168 */ 1169 protected void initCmsContextForUI(HttpServletRequest req, HttpServletResponse res, CmsUIServlet servlet) 1170 throws IOException, CmsException { 1171 1172 // instantiate CMS context 1173 String originalEncoding = req.getCharacterEncoding(); 1174 String referrer = req.getHeader("referer"); 1175 boolean allowPrivilegedLogin = (referrer == null) || !referrer.contains(CmsWorkplaceLoginHandler.LOGIN_HANDLER); 1176 1177 CmsObject cms = initCmsObject(req, res, allowPrivilegedLogin); 1178 servlet.setCms(cms); 1179 if (originalEncoding != null) { 1180 // getI18NInfo sets wrong encoding 1181 req.setCharacterEncoding(originalEncoding); 1182 } 1183 } 1184 1185 /** 1186 * Returns an independent copy of the provided CmsObject.<p> 1187 * 1188 * This can be useful in case a permanent reference to a CmsObject is stored. 1189 * Changing the request context values (for example project, siteroot) in the new CmsObject 1190 * will have no side effects to the CmsObject it was copied form.<p> 1191 * 1192 * The request time (<code>{@link CmsRequestContext#getRequestTime()}</code>) 1193 * is set to the current time.<p> 1194 * 1195 * @param cms the CmsObject to create a copy of 1196 * 1197 * @return an independent copy of the provided CmsObject 1198 * 1199 * @throws CmsException in case the initialization failed 1200 * 1201 * @see OpenCms#initCmsObject(CmsObject) 1202 * @see OpenCms#initCmsObject(CmsObject, CmsContextInfo) 1203 * @see OpenCms#initCmsObject(String) 1204 */ 1205 protected CmsObject initCmsObject(CmsObject cms) { 1206 1207 CmsRequestContext requestContext = cms.getRequestContext(); 1208 CmsRequestContext context = new CmsRequestContext( 1209 requestContext.getCurrentUser().clone(), 1210 (CmsProject)(requestContext.getCurrentProject().clone()), 1211 requestContext.getUri(), 1212 requestContext.getRequestMatcher(), 1213 requestContext.getSiteRoot(), 1214 requestContext.isSecureRequest(), 1215 requestContext.getLocale(), 1216 requestContext.getEncoding(), 1217 requestContext.getRemoteAddress(), 1218 System.currentTimeMillis(), 1219 m_resourceManager.getFolderTranslator(), 1220 m_resourceManager.getFileTranslator(), 1221 requestContext.getOuFqn(), 1222 requestContext.isForceAbsoluteLinks()); 1223 context.setDetailResource(requestContext.getDetailResource()); 1224 CmsObject result = new CmsObject(m_securityManager, context); 1225 return result; 1226 } 1227 1228 /** 1229 * Returns an initialized CmsObject with the user and context initialized as provided.<p> 1230 * 1231 * Note: Only if the provided <code>adminCms</code> CmsObject has admin permissions, 1232 * this method allows the creation a CmsObject for any existing user. Otherwise 1233 * only the default users 'Guest' and 'Export' can initialized with 1234 * this method, all other user names will throw an Exception.<p> 1235 * 1236 * @param adminCms must either be initialized with "Admin" permissions, or null 1237 * @param contextInfo the context info to create a CmsObject for 1238 * 1239 * @return an initialized CmsObject with the given users permissions 1240 * 1241 * @throws CmsException if an invalid user name was provided 1242 * @throws CmsRoleViolationException if the current user does not have the role permissions to create a context for the requested user 1243 * 1244 * @see org.opencms.db.CmsDefaultUsers#getUserGuest() 1245 * @see org.opencms.db.CmsDefaultUsers#getUserExport() 1246 * @see OpenCms#initCmsObject(CmsObject) 1247 * @see OpenCms#initCmsObject(CmsObject, CmsContextInfo) 1248 * @see OpenCms#initCmsObject(String) 1249 */ 1250 protected CmsObject initCmsObject(CmsObject adminCms, CmsContextInfo contextInfo) 1251 throws CmsRoleViolationException, CmsException { 1252 1253 String userName = contextInfo.getUserName(); 1254 1255 if ((adminCms == null) || !m_roleManager.hasRole(adminCms, CmsRole.ROOT_ADMIN)) { 1256 if (!userName.endsWith(getDefaultUsers().getUserGuest()) 1257 && !userName.endsWith(getDefaultUsers().getUserExport())) { 1258 1259 // if no admin object is provided, only "Guest" or "Export" user can be generated 1260 CmsMessageContainer message = Messages.get().container( 1261 Messages.ERR_INVALID_INIT_USER_2, 1262 userName, 1263 ((adminCms != null) ? (adminCms.getRequestContext().getCurrentUser().getName()) : "")); 1264 if (LOG.isWarnEnabled()) { 1265 LOG.warn(message.key()); 1266 } 1267 throw new CmsRoleViolationException(message); 1268 } 1269 } 1270 1271 return initCmsObject(contextInfo); 1272 } 1273 1274 /** 1275 * Handles the user authentification for each request sent to OpenCms.<p> 1276 * 1277 * User authentification is done in three steps: 1278 * <ol> 1279 * <li>Session authentification: OpenCms stores information of all authentificated 1280 * users in an internal storage based on the users session.</li> 1281 * <li>Authorization handler authentification: If the session authentification fails, 1282 * the current configured authorization handler is called.</li> 1283 * <li>Default user: When both authentification methods fail, the user is set to 1284 * the default (Guest) user.</li> 1285 * </ol> 1286 * 1287 * @param req the current http request 1288 * @param res the current http response 1289 * @param allowPrivilegedLogin <code>true</code> to allow login through authorization handlers 1290 * 1291 * @return the initialized cms context 1292 * 1293 * @throws IOException if user authentication fails 1294 * @throws CmsException in case something goes wrong 1295 */ 1296 protected CmsObject initCmsObject(HttpServletRequest req, HttpServletResponse res, boolean allowPrivilegedLogin) 1297 throws IOException, CmsException { 1298 1299 // first try to restore a stored session 1300 CmsObject cms = initCmsObjectFromSession(req); 1301 if (cms != null) { 1302 return cms; 1303 } 1304 if (allowPrivilegedLogin) { 1305 // if does not work, try to authorize the request 1306 I_CmsAuthorizationHandler.I_PrivilegedLoginAction loginAction = new I_CmsAuthorizationHandler.I_PrivilegedLoginAction() { 1307 1308 private CmsObject m_adminCms; 1309 1310 /** 1311 * @see org.opencms.security.I_CmsAuthorizationHandler.I_PrivilegedLoginAction#doLogin(jakarta.servlet.http.HttpServletRequest, java.lang.String) 1312 */ 1313 public CmsObject doLogin(HttpServletRequest request, String principal) throws CmsException { 1314 1315 try { 1316 CmsUser user = m_adminCms.readUser(principal); 1317 if (!user.isEnabled()) { 1318 throw new CmsException( 1319 Messages.get().container(Messages.ERR_INVALID_INIT_USER_2, user.getName(), "-")); 1320 } 1321 1322 // initialize the new cms object 1323 CmsContextInfo contextInfo = new CmsContextInfo(m_adminCms.getRequestContext()); 1324 contextInfo.setUserName(principal); 1325 CmsObject newCms = initCmsObject(m_adminCms, contextInfo); 1326 1327 if ((contextInfo.getRequestedUri().startsWith("/system/workplace/") 1328 // also check for new workplace 1329 || request.getRequestURI().startsWith(OpenCms.getSystemInfo().getWorkplaceContext())) 1330 && getRoleManager().hasRole(newCms, CmsRole.ELEMENT_AUTHOR)) { 1331 LOG.debug("Handling workplace login for user " + principal); 1332 CmsWorkplaceSettings settings = CmsLoginHelper.initSiteAndProject(newCms); 1333 request.getSession(true).setAttribute( 1334 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS, 1335 settings); 1336 OpenCms.getSessionManager().updateSessionInfo(newCms, request); 1337 } 1338 m_adminCms.updateLastLoginDate(user); 1339 1340 // fire the login user event 1341 OpenCms.fireCmsEvent( 1342 I_CmsEventListener.EVENT_LOGIN_USER, 1343 Collections.<String, Object> singletonMap("data", user)); 1344 return newCms; 1345 } finally { 1346 m_adminCms = null; 1347 } 1348 } 1349 1350 /** 1351 * @see org.opencms.security.I_CmsAuthorizationHandler.I_PrivilegedLoginAction#getCmsObject() 1352 */ 1353 public CmsObject getCmsObject() { 1354 1355 return m_adminCms; 1356 } 1357 1358 /** 1359 * @see org.opencms.security.I_CmsAuthorizationHandler.I_PrivilegedLoginAction#setCmsObject(org.opencms.file.CmsObject) 1360 */ 1361 public void setCmsObject(CmsObject adminCms) { 1362 1363 m_adminCms = adminCms; 1364 } 1365 }; 1366 loginAction.setCmsObject(initCmsObject(req, res, OpenCms.getDefaultUsers().getUserAdmin(), null, null)); 1367 cms = m_authorizationHandler.initCmsObject(req, loginAction); 1368 if (cms != null) { 1369 return cms; 1370 } 1371 1372 // authentification failed or not enough permissions, so display a login screen 1373 m_authorizationHandler.requestAuthorization(req, res, getLoginFormURL(req, res)); 1374 } 1375 cms = initCmsObject( 1376 req, 1377 m_securityManager.readUser(null, OpenCms.getDefaultUsers().getUserGuest()), 1378 getSiteManager().matchRequest(req).getSiteRoot(), 1379 CmsProject.ONLINE_PROJECT_ID, 1380 ""); 1381 // return the initialized cms user context object 1382 return cms; 1383 } 1384 1385 /** 1386 * Returns an initialized CmsObject with the user initialized as provided, 1387 * with the "Online" project selected and "/" set as the current site root.<p> 1388 * 1389 * Note: Only the default users 'Guest' and 'Export' can initialized with 1390 * this method, all other user names will throw an Exception.<p> 1391 * 1392 * @param user the user name to initialize, can only be 1393 * {@link org.opencms.db.CmsDefaultUsers#getUserGuest()} or 1394 * {@link org.opencms.db.CmsDefaultUsers#getUserExport()} 1395 * 1396 * @return an initialized CmsObject with the given users permissions 1397 * 1398 * @throws CmsException if an invalid user name was provided, or if something else goes wrong 1399 * 1400 * @see org.opencms.db.CmsDefaultUsers#getUserGuest() 1401 * @see org.opencms.db.CmsDefaultUsers#getUserExport() 1402 * @see OpenCms#initCmsObject(String) 1403 * @see #initCmsObject(CmsObject, CmsContextInfo) 1404 */ 1405 protected CmsObject initCmsObject(String user) throws CmsException { 1406 1407 return initCmsObject(null, new CmsContextInfo(user)); 1408 } 1409 1410 /** 1411 * Initializes a new cms object from the session data of the request.<p> 1412 * 1413 * If no session data is found, <code>null</code> is returned.<p> 1414 * 1415 * @param req the request 1416 * 1417 * @return the new initialized cms object 1418 * 1419 * @throws CmsException if something goes wrong 1420 */ 1421 protected CmsObject initCmsObjectFromSession(HttpServletRequest req) throws CmsException { 1422 1423 String url = req.getRequestURL().toString(); 1424 String p = "[ " + url + " ] "; 1425 if (LOG.isDebugEnabled()) { 1426 LOG.debug(p + "Trying to init cms object from session for request \"" + req.toString() + "\"."); 1427 } 1428 // try to get an OpenCms user session info object for this request 1429 CmsSessionInfo sessionInfo = m_sessionManager.getSessionInfo(req); 1430 1431 if (sessionInfo == null) { 1432 if (LOG.isDebugEnabled()) { 1433 LOG.debug(p + "No session info found."); 1434 } 1435 return null; 1436 } 1437 if (!getSessionManager().hasValidClientToken(req)) { 1438 if (LOG.isDebugEnabled()) { 1439 LOG.debug("Client token in session invalid."); 1440 } 1441 return null; 1442 } 1443 1444 // initialize the requested site root 1445 CmsSite site = getSiteManager().matchRequest(req); 1446 1447 // a user name is found in the session manager, reuse this user information 1448 CmsUUID project = sessionInfo.getProject(); 1449 1450 // initialize site root from request 1451 String siteroot = sessionInfo.getSiteRoot(); 1452 if (siteroot == null) { 1453 // not sure if this can actually happen? 1454 LOG.debug(p + "site root from session info was null, determining site root from current request's host"); 1455 siteroot = site.getSiteRoot(); 1456 } 1457 // initialize user from request 1458 CmsUser user = m_securityManager.readUser(null, sessionInfo.getUserId()); 1459 1460 if (LOG.isDebugEnabled()) { 1461 LOG.debug(p + "Initializing cms object with user \"" + user.getName() + "\"."); 1462 LOG.debug(p + "siteRoot = " + siteroot); 1463 } 1464 return initCmsObject(req, user, siteroot, project, sessionInfo.getOrganizationalUnitFqn()); 1465 } 1466 1467 /** 1468 * Constructor to create a new OpenCms object.<p> 1469 * 1470 * It reads the configurations from the <code>opencms.properties</code> 1471 * file in the <code>config/</code> subdirectory. With the information 1472 * from this file is inits a ResourceBroker (Database access module), 1473 * various caching systems and other options.<p> 1474 * 1475 * This will only be done once per accessing class. 1476 * 1477 * @param configuration the configurations from the <code>opencms.properties</code> file 1478 * @throws CmsInitException in case OpenCms can not be initialized 1479 */ 1480 protected synchronized void initConfiguration(CmsParameterConfiguration configuration) throws CmsInitException { 1481 1482 String serverInfo = configuration.getString("context.servlet.container", null); 1483 1484 // output startup message to log file 1485 if (CmsLog.INIT.isInfoEnabled()) { 1486 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 1487 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 1488 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 1489 CmsLog.INIT.info( 1490 ". " 1491 + Messages.get().getBundle().key( 1492 Messages.GUI_SHELL_VERSION_1, 1493 OpenCms.getSystemInfo().getVersionNumber())); 1494 for (int i = 0; i < Messages.COPYRIGHT_BY_ALKACON.length; i++) { 1495 CmsLog.INIT.info(". " + Messages.COPYRIGHT_BY_ALKACON[i]); 1496 } 1497 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LINE_0)); 1498 CmsLog.INIT.info( 1499 Messages.get().getBundle().key(Messages.INIT_STARTUP_TIME_1, new Date(System.currentTimeMillis()))); 1500 CmsLog.INIT.info( 1501 Messages.get().getBundle().key( 1502 Messages.INIT_OPENCMS_VERSION_1, 1503 OpenCms.getSystemInfo().getVersionNumber() + " [" + OpenCms.getSystemInfo().getVersionId() + "]")); 1504 if (serverInfo != null) { 1505 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SERVLET_CONTAINER_1, serverInfo)); 1506 } 1507 CmsLog.INIT.info( 1508 Messages.get().getBundle().key(Messages.INIT_WEBAPP_NAME_1, getSystemInfo().getWebApplicationName())); 1509 CmsLog.INIT.info( 1510 Messages.get().getBundle().key(Messages.INIT_SERVLET_PATH_1, getSystemInfo().getServletPath())); 1511 CmsLog.INIT.info( 1512 Messages.get().getBundle().key(Messages.INIT_OPENCMS_CONTEXT_1, getSystemInfo().getOpenCmsContext())); 1513 CmsLog.INIT.info( 1514 Messages.get().getBundle().key(Messages.INIT_WEBINF_PATH_1, getSystemInfo().getWebInfRfsPath())); 1515 CmsLog.INIT.info( 1516 Messages.get().getBundle().key( 1517 Messages.INIT_PROPERTY_FILE_1, 1518 getSystemInfo().getConfigurationFileRfsPath())); 1519 1520 String logFileRfsPath = getSystemInfo().getLogFileRfsPath(); 1521 CmsLog.INIT.info( 1522 Messages.get().getBundle().key( 1523 Messages.INIT_LOG_FILE_1, 1524 logFileRfsPath != null ? logFileRfsPath : "Managed by log4j")); 1525 } 1526 1527 String systemEncoding = null; 1528 try { 1529 systemEncoding = System.getProperty("file.encoding"); 1530 } catch (SecurityException se) { 1531 // security manager is active, but we will try other options before giving up 1532 LOG.debug("Security manager preventing access to file.encoding system property.", se); 1533 } 1534 try { 1535 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 1536 } catch (Exception e) { 1537 CmsLog.INIT.error(e.getLocalizedMessage(), e); 1538 } 1539 if (CmsLog.INIT.isInfoEnabled()) { 1540 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FILE_ENCODING_1, systemEncoding)); 1541 } 1542 1543 // read server ethernet address (MAC) and init UUID generator 1544 String ethernetAddress = configuration.getString("server.ethernet.address", CmsStringUtil.getEthernetAddress()); 1545 if (CmsLog.INIT.isInfoEnabled()) { 1546 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ETHERNET_ADDRESS_1, ethernetAddress)); 1547 } 1548 CmsUUID.init(ethernetAddress); 1549 1550 // set the server name 1551 String serverName = configuration.getString("server.name", "OpenCmsServer"); 1552 getSystemInfo().setServerName(serverName); 1553 1554 // check the installed Java SDK 1555 try { 1556 if (CmsLog.INIT.isInfoEnabled()) { 1557 String jdkinfo = System.getProperty("java.vm.name") + " "; 1558 jdkinfo += System.getProperty("java.vm.version") + " "; 1559 jdkinfo += System.getProperty("java.vm.info") + " "; 1560 jdkinfo += System.getProperty("java.vm.vendor") + " "; 1561 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_JAVA_VM_1, jdkinfo)); 1562 String osinfo = System.getProperty("os.name") + " "; 1563 osinfo += System.getProperty("os.version") + " "; 1564 osinfo += System.getProperty("os.arch") + " "; 1565 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_OPERATING_SYSTEM_1, osinfo)); 1566 } 1567 } catch (Exception e) { 1568 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_PROP_0), e); 1569 } 1570 1571 // create the configuration manager instance 1572 m_configurationManager = new CmsConfigurationManager(getSystemInfo().getConfigFolder()); 1573 // store the configuration read from "opencms.properties" in the configuration manager 1574 m_configurationManager.setConfiguration(configuration); 1575 1576 // now load the XML configuration 1577 try { 1578 m_configurationManager.loadXmlConfiguration(); 1579 } catch (Exception e) { 1580 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_XML_0), e); 1581 } 1582 1583 // get the system configuration 1584 CmsSystemConfiguration systemConfiguration = (CmsSystemConfiguration)m_configurationManager.getConfiguration( 1585 CmsSystemConfiguration.class); 1586 1587 if (systemConfiguration.useSaxImplSystemProperties()) { 1588 CmsXmlUtils.initSystemProperties(); 1589 } 1590 1591 // initialize the memory monitor 1592 CmsMemoryMonitorConfiguration memoryMonitorConfiguration = systemConfiguration.getCmsMemoryMonitorConfiguration(); 1593 // initialize the memory monitor 1594 try { 1595 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(memoryMonitorConfiguration.getClassName())) { 1596 m_memoryMonitor = (CmsMemoryMonitor)Class.forName( 1597 memoryMonitorConfiguration.getClassName()).getDeclaredConstructor().newInstance(); 1598 } else { 1599 m_memoryMonitor = new CmsMemoryMonitor(); 1600 } 1601 } catch (Exception e) { 1602 // we can not start without a valid memory monitor 1603 throw new CmsInitException( 1604 Messages.get().container( 1605 Messages.ERR_CRITICAL_INIT_MEMORY_MONITOR_1, 1606 memoryMonitorConfiguration.getClassName()), 1607 e); 1608 } 1609 m_memoryMonitor.initialize(systemConfiguration); 1610 1611 // get the event manager from the configuration and initialize it with the events already registered 1612 CmsEventManager configuredEventManager = systemConfiguration.getEventManager(); 1613 configuredEventManager.initialize(m_eventManager); 1614 m_eventManager = configuredEventManager; 1615 1616 // check if the encoding setting is valid 1617 String setEncoding = systemConfiguration.getDefaultContentEncoding(); 1618 String defaultEncoding = CmsEncoder.lookupEncoding(setEncoding, null); 1619 if (defaultEncoding == null) { 1620 // we can not start without a valid encoding setting 1621 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_ENCODING_1, setEncoding)); 1622 } 1623 if (CmsLog.INIT.isInfoEnabled()) { 1624 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_OPENCMS_ENCODING_1, defaultEncoding)); 1625 } 1626 getSystemInfo().setDefaultEncoding(defaultEncoding); 1627 1628 // set version history information 1629 getSystemInfo().setVersionHistorySettings( 1630 systemConfiguration.isHistoryEnabled(), 1631 systemConfiguration.getHistoryVersions(), 1632 systemConfiguration.getHistoryVersionsAfterDeletion()); 1633 // set mail configuration 1634 getSystemInfo().setMailSettings(systemConfiguration.getMailSettings()); 1635 // set HTTP authentication settings 1636 getSystemInfo().setHttpAuthenticationSettings(systemConfiguration.getHttpAuthenticationSettings()); 1637 getSystemInfo().setRestrictDetailContents(systemConfiguration.isRestrictDetailContents()); 1638 1639 // set content notification settings 1640 getSystemInfo().setNotificationTime(systemConfiguration.getNotificationTime()); 1641 getSystemInfo().setNotificationProject(systemConfiguration.getNotificationProject()); 1642 m_executor = new ScheduledThreadPoolExecutor( 1643 3, 1644 new ThreadFactoryBuilder().setNameFormat("OpenCmsCore-exec-%d").build()); 1645 // set resource init classes 1646 1647 m_resourceInitHandlers = systemConfiguration.getResourceInitHandlers(); 1648 1649 // register request handler classes 1650 Iterator<I_CmsRequestHandler> it = systemConfiguration.getRequestHandlers().iterator(); 1651 while (it.hasNext()) { 1652 I_CmsRequestHandler handler = it.next(); 1653 addRequestHandler(handler); 1654 if (CmsLog.INIT.isInfoEnabled()) { 1655 CmsLog.INIT.info( 1656 Messages.get().getBundle().key( 1657 Messages.INIT_REQUEST_HANDLER_CLASS_1, 1658 handler.getClass().getName())); 1659 } 1660 } 1661 1662 // read the default user configuration 1663 m_defaultUsers = systemConfiguration.getCmsDefaultUsers(); 1664 1665 // get the site manager from the configuration 1666 CmsSitesConfiguration sitesConfiguration = (CmsSitesConfiguration)m_configurationManager.getConfiguration( 1667 CmsSitesConfiguration.class); 1668 m_siteManager = sitesConfiguration.getSiteManager(); 1669 1670 CmsSchedulerConfiguration schedulerConfiguration = (CmsSchedulerConfiguration)m_configurationManager.getConfiguration( 1671 CmsSchedulerConfiguration.class); 1672 // set the scheduler manager 1673 m_scheduleManager = schedulerConfiguration.getScheduleManager(); 1674 1675 CmsVariablesConfiguration variablesConfiguration = (CmsVariablesConfiguration)m_configurationManager.getConfiguration( 1676 CmsVariablesConfiguration.class); 1677 1678 // get the VFS / resource configuration 1679 CmsVfsConfiguration vfsConfiguation = (CmsVfsConfiguration)m_configurationManager.getConfiguration( 1680 CmsVfsConfiguration.class); 1681 m_resourceManager = vfsConfiguation.getResourceManager(); 1682 I_CmsResourceLoader imageLoader = m_resourceManager.getLoader(CmsImageLoader.RESOURCE_LOADER_ID_IMAGE_LOADER); 1683 if (imageLoader instanceof CmsImageLoader) { 1684 try { 1685 ((CmsImageLoader)imageLoader).initializeImageCache(configuration); 1686 } catch (CmsConfigurationException e) { 1687 throw new CmsInitException(e.getMessageContainer(), e); 1688 } 1689 } 1690 m_xmlContentTypeManager = vfsConfiguation.getXmlContentTypeManager(); 1691 m_defaultFiles = vfsConfiguation.getDefaultFiles(); 1692 1693 // initialize translation engines 1694 m_resourceManager.setTranslators( 1695 vfsConfiguation.getFolderTranslator(), 1696 vfsConfiguation.getFileTranslator(), 1697 vfsConfiguation.getXsdTranslator()); 1698 1699 // try to initialize the flex cache 1700 CmsFlexCache flexCache = null; 1701 try { 1702 if (CmsLog.INIT.isInfoEnabled()) { 1703 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FLEX_CACHE_STARTING_0)); 1704 } 1705 // get the flex cache configuration from the SystemConfiguration 1706 CmsFlexCacheConfiguration flexCacheConfiguration = systemConfiguration.getCmsFlexCacheConfiguration(); 1707 getSystemInfo().setDeviceSelector(flexCacheConfiguration.getDeviceSelector()); 1708 // pass configuration to flex cache for initialization 1709 flexCache = new CmsFlexCache(flexCacheConfiguration); 1710 m_flexCache = flexCache; 1711 if (CmsLog.INIT.isInfoEnabled()) { 1712 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FLEX_CACHE_FINISHED_0)); 1713 } 1714 } catch (Exception e) { 1715 if (CmsLog.INIT.isWarnEnabled()) { 1716 CmsLog.INIT.warn(Messages.get().getBundle().key(Messages.INIT_FLEX_CACHE_ERROR_1, e.getMessage())); 1717 } 1718 } 1719 1720 if (flexCache != null) { 1721 // check all resource loaders if they require the Flex cache 1722 Iterator<I_CmsResourceLoader> i = m_resourceManager.getLoaders().iterator(); 1723 while (i.hasNext()) { 1724 Object o = i.next(); 1725 if (o instanceof I_CmsFlexCacheEnabledLoader) { 1726 // this resource loader requires the Flex cache 1727 ((I_CmsFlexCacheEnabledLoader)o).setFlexCache(flexCache); 1728 } 1729 } 1730 } 1731 1732 // get the import/export configuration 1733 CmsImportExportConfiguration importExportConfiguration = (CmsImportExportConfiguration)m_configurationManager.getConfiguration( 1734 CmsImportExportConfiguration.class); 1735 try { 1736 importExportConfiguration.validate(); 1737 } catch (CmsConfigurationException e) { 1738 throw new CmsInitException(e.getMessageContainer(), e); 1739 } 1740 m_importExportManager = importExportConfiguration.getImportExportManager(); 1741 m_staticExportManager = importExportConfiguration.getStaticExportManager(); 1742 m_staticExportManager.setStoredContentDeliveryConfiguration( 1743 importExportConfiguration.getStoredContentDeliveryConfiguration()); 1744 m_staticExportManager.setSharedCacheConfiguration(importExportConfiguration.getSharedCacheConfiguration()); 1745 m_repositoryManager = importExportConfiguration.getRepositoryManager(); 1746 1747 // get the search configuration 1748 CmsSearchConfiguration searchConfiguration = (CmsSearchConfiguration)m_configurationManager.getConfiguration( 1749 CmsSearchConfiguration.class); 1750 m_searchManager = searchConfiguration.getSearchManager(); 1751 1752 // get the workplace configuration 1753 CmsWorkplaceConfiguration workplaceConfiguration = (CmsWorkplaceConfiguration)m_configurationManager.getConfiguration( 1754 CmsWorkplaceConfiguration.class); 1755 m_workplaceManager = workplaceConfiguration.getWorkplaceManager(); 1756 // add the export points from the workplace 1757 addExportPoints(m_workplaceManager.getExportPoints()); 1758 addExportPoints(m_staticExportManager.getExportPoints()); 1759 1760 // get the module configuration 1761 CmsModuleConfiguration moduleConfiguration = (CmsModuleConfiguration)m_configurationManager.getConfiguration( 1762 CmsModuleConfiguration.class); 1763 m_moduleManager = moduleConfiguration.getModuleManager(); 1764 1765 // get the password handler 1766 m_passwordHandler = systemConfiguration.getPasswordHandler(); 1767 1768 // get the validation handler 1769 m_validationHandler = systemConfiguration.getValidationHandler(); 1770 1771 // get the authorization handler 1772 m_authorizationHandler = systemConfiguration.getAuthorizationHandler(); 1773 1774 // get the login manager 1775 m_loginManager = systemConfiguration.getLoginManager(); 1776 // set the login message 1777 try { 1778 m_loginManager.setLoginMessage(null, variablesConfiguration.getLoginMessage()); 1779 m_loginManager.setBeforeLoginMessage(null, variablesConfiguration.getBeforeLoginMessage()); 1780 } catch (CmsRoleViolationException e1) { 1781 CmsLog.INIT.error(e1.getLocalizedMessage(), e1); 1782 } 1783 1784 // initialize the publish engine 1785 m_publishEngine = new CmsPublishEngine(systemConfiguration.getRuntimeInfoFactory()); 1786 1787 // Credentials resolver - needs to be set before the driver manager is initialized 1788 m_credentialsResolver = systemConfiguration.getCredentialsResolver(); 1789 1790 m_secretStore = systemConfiguration.getSecretStore(); 1791 1792 m_elementMarker = systemConfiguration.getElementMarker(); 1793 1794 // init the OpenCms security manager 1795 m_securityManager = CmsSecurityManager.newInstance( 1796 m_configurationManager, 1797 systemConfiguration.getRuntimeInfoFactory(), 1798 m_publishEngine); 1799 1800 // get the publish manager 1801 m_publishManager = systemConfiguration.getPublishManager(); 1802 1803 // get the subscription manager 1804 m_subscriptionManager = systemConfiguration.getSubscriptionManager(); 1805 1806 // initialize the role manager 1807 m_roleManager = new CmsRoleManager(m_securityManager); 1808 1809 // initialize the organizational unit manager 1810 m_orgUnitManager = new CmsOrgUnitManager(m_securityManager); 1811 1812 // initialize the Thread store 1813 m_threadStore = new CmsThreadStore(m_securityManager); 1814 1815 // initialize the link manager 1816 m_linkManager = new CmsLinkManager(m_staticExportManager.getLinkSubstitutionHandler()); 1817 1818 m_aliasManager = new CmsAliasManager(m_securityManager); 1819 1820 // store the runtime properties 1821 m_runtimeProperties.putAll(systemConfiguration.getRuntimeProperties()); 1822 1823 // initialize the session storage provider 1824 I_CmsSessionStorageProvider sessionStorageProvider = systemConfiguration.getSessionStorageProvider(); 1825 1826 // get an Admin cms context object with site root set to "/" 1827 CmsObject adminCms; 1828 try { 1829 adminCms = initCmsObject(null, null, getDefaultUsers().getUserAdmin(), (String)null, (String)null); 1830 } catch (CmsException e) { 1831 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_ADMINCMS_0), e); 1832 } 1833 m_configAdminCms = adminCms; 1834 1835 m_repositoryManager.initializeCms(adminCms); 1836 // now initialize the other managers 1837 try { 1838 if (flexCache != null) { 1839 flexCache.initializeCms(initCmsObject(adminCms)); 1840 } 1841 1842 m_configurationManager.setAdminCms(adminCms); 1843 1844 // initialize the scheduler 1845 m_scheduleManager.initialize(initCmsObject(adminCms)); 1846 1847 // initialize the locale manager 1848 m_localeManager = systemConfiguration.getLocaleManager(); 1849 m_localeManager.initialize(initCmsObject(adminCms)); 1850 1851 // initialize the site manager 1852 m_siteManager.initialize(initCmsObject(adminCms)); 1853 1854 // initialize the static export manager 1855 m_staticExportManager.initialize(initCmsObject(adminCms)); 1856 1857 // initialize the XML content type manager 1858 m_xmlContentTypeManager.initialize(initCmsObject(adminCms)); 1859 1860 m_orgUnitManager.initialize(initCmsObject(adminCms)); 1861 1862 // initialize the module manager 1863 m_moduleManager.initialize(initCmsObject(adminCms), m_configurationManager); 1864 1865 // initialize the resource manager 1866 m_resourceManager.initialize(initCmsObject(adminCms)); 1867 1868 // initialize the publish manager 1869 m_publishManager.setPublishEngine(m_publishEngine); 1870 m_publishManager.setSecurityManager(m_securityManager); 1871 m_publishManager.setPublishListRemoveMode(systemConfiguration.getPublishListRemoveMode()); 1872 m_publishManager.initialize(initCmsObject(adminCms)); 1873 1874 // initialize the search manager 1875 m_searchManager.initialize(initCmsObject(adminCms)); 1876 1877 // initialize the VFS bundle manager 1878 m_vfsBundleManager = new CmsVfsBundleManager(adminCms); 1879 1880 // initialize the workplace manager 1881 m_workplaceManager.initialize(initCmsObject(adminCms)); 1882 1883 // initialize the session manager 1884 m_sessionManager.initialize(sessionStorageProvider, initCmsObject(adminCms)); 1885 m_sessionManager.setUserSessionMode(systemConfiguration.getUserSessionMode(true)); 1886 1887 // initialize the subscription manager 1888 m_subscriptionManager.setSecurityManager(m_securityManager); 1889 m_subscriptionManager.initialize(adminCms); 1890 1891 CmsUgcSessionFactory.setAdminCms(adminCms); 1892 1893 // initialize the formatter configuration 1894 CmsFormatterConfiguration.initialize(adminCms); 1895 CmsPersistentLoginTokenHandler.setAdminCms(initCmsObject(adminCms)); 1896 CmsLoginUI.setAdminCmsObject(initCmsObject(adminCms)); 1897 1898 // initialize ade manager 1899 m_adeManager = new CmsADEManager(initCmsObject(adminCms), m_memoryMonitor, systemConfiguration); 1900 m_workplaceAppManager = new CmsWorkplaceAppManager(initCmsObject(adminCms)); 1901 m_workplaceAppManager.loadApps(); 1902 m_workplaceAppManager.initWorkplaceCssUris(m_moduleManager); 1903 1904 m_templateContextManager = new CmsTemplateContextManager(initCmsObject(adminCms)); 1905 m_workflowManager = systemConfiguration.getWorkflowManager(); 1906 m_letsEncryptConfig = systemConfiguration.getLetsEncryptConfig(); 1907 1908 m_userDataRequestManager = systemConfiguration.getUserDataRequestManager(); 1909 if (m_userDataRequestManager != null) { 1910 m_userDataRequestManager.initialize(initCmsObject(adminCms)); 1911 } 1912 1913 if (m_workflowManager == null) { 1914 m_workflowManager = new CmsDefaultWorkflowManager(); 1915 m_workflowManager.setParameters(new HashMap<String, String>()); 1916 } 1917 1918 m_remoteShellServer = CmsRemoteShellServer.initialize(systemConfiguration); 1919 1920 CmsPublishScheduledDialog.setAdminCms(initCmsObject(adminCms)); 1921 1922 m_workflowManager.initialize(initCmsObject(adminCms)); 1923 m_apiAuthorizations = systemConfiguration.getApiAuthorizations(); 1924 for (I_CmsApiAuthorizationHandler apiAuthorization : m_apiAuthorizations.values()) { 1925 apiAuthorization.initialize(initCmsObject(adminCms)); 1926 } 1927 1928 for (I_CmsResourceInit resourceInit : m_resourceInitHandlers) { 1929 if (resourceInit instanceof I_CmsNeedsAdminCmsObject) { 1930 ((I_CmsNeedsAdminCmsObject)resourceInit).setAdminCmsObject(adminCms); 1931 } 1932 } 1933 for (I_CmsRequestHandler requestHandler : m_requestHandlers.values()) { 1934 if (requestHandler instanceof I_CmsNeedsAdminCmsObject) { 1935 ((I_CmsNeedsAdminCmsObject)requestHandler).setAdminCmsObject(adminCms); 1936 } 1937 } 1938 1939 if (m_loginManager.getCustomLogin() != null) { 1940 m_loginManager.getCustomLogin().initialize(initCmsObject(adminCms)); 1941 } 1942 1943 m_textEncryptions = new LinkedHashMap<>(); 1944 for (I_CmsTextEncryption encryption : systemConfiguration.getTextEncryptions().values()) { 1945 encryption.initialize(OpenCms.initCmsObject(adminCms)); 1946 m_textEncryptions.put(encryption.getName(), encryption); 1947 } 1948 1949 m_twoFactorAuthenticationHandler = new CmsTwoFactorAuthenticationHandler( 1950 OpenCms.initCmsObject(adminCms), 1951 systemConfiguration.getTwoFactorAuthenticationConfig()); 1952 1953 m_secretStore.initialize(initCmsObject(adminCms)); 1954 1955 } catch (CmsException e) { 1956 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_MANAGERS_0), e); 1957 } 1958 1959 try { 1960 // mitigate potential stringtemplate 3 class loading deadlock by making sure the class is loaded on startup 1961 @SuppressWarnings("unused") 1962 StringTemplate stringTemplate = new org.antlr.stringtemplate.StringTemplate(); 1963 } catch (Exception e) { 1964 CmsLog.INIT.error("Problem with initializing stringtemplate class: " + e.getLocalizedMessage(), e); 1965 } 1966 1967 try { 1968 CmsModificationContext.initialize( 1969 m_securityManager, 1970 initCmsObject(adminCms), 1971 vfsConfiguation.getOnlineFolderOptions()); 1972 } catch (Exception e) { 1973 CmsLog.INIT.error("Problem with initializing modification context"); 1974 } 1975 1976 try { 1977 getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES); 1978 } catch (Exception e) { 1979 CmsLog.INIT.error("Problem with clearing caches after initialization: " + e.getLocalizedMessage(), e); 1980 } 1981 CmsTaskWatcher.initialize(); 1982 } 1983 1984 /** 1985 * Initialization of the OpenCms runtime environment.<p> 1986 * 1987 * The connection information for the database is read 1988 * from the <code>opencms.properties</code> configuration file and all 1989 * driver manager are initialized via the initializer, 1990 * which usually will be an instance of a <code>OpenCms</code> class. 1991 * 1992 * @param context configuration of OpenCms from <code>web.xml</code> 1993 * @throws CmsInitException in case OpenCms can not be initialized 1994 */ 1995 protected synchronized void initContext(ServletContext context) throws CmsInitException { 1996 1997 m_gwtServiceContexts = new HashMap<String, CmsGwtServiceContext2>(); 1998 1999 // automatic servlet container recognition and specific behavior: 2000 CmsServletContainerSettings servletContainerSettings = new CmsServletContainerSettings(context); 2001 getSystemInfo().init(servletContainerSettings); 2002 getSystemInfo().initJavaEeVersion(context.getMajorVersion(), context.getMinorVersion()); 2003 2004 // Collect the configurations 2005 CmsParameterConfiguration configuration; 2006 try { 2007 configuration = new CmsParameterConfiguration(getSystemInfo().getConfigurationFileRfsPath()); 2008 } catch (Exception e) { 2009 throw new CmsInitException( 2010 Messages.get().container( 2011 Messages.ERR_CRITICAL_INIT_PROPFILE_1, 2012 getSystemInfo().getConfigurationFileRfsPath()), 2013 e); 2014 } 2015 2016 String throwException = configuration.getString("servlet.exception.enabled", "auto"); 2017 if (!throwException.equals("auto")) { 2018 // set the parameter is not automatic, the rest of the servlet container dependent parameters 2019 // will be set when reading the system configuration, if not set to auto 2020 boolean throwExc = Boolean.valueOf(throwException).booleanValue(); 2021 getSystemInfo().getServletContainerSettings().setServletThrowsException(throwExc); 2022 } 2023 2024 // check if the wizard is enabled, if so stop initialization 2025 if (configuration.getBoolean("wizard.enabled", true)) { 2026 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_WIZARD_0)); 2027 } 2028 2029 // add an indicator that the configuration was processed from the servlet context 2030 configuration.add("context.servlet.container", context.getServerInfo()); 2031 2032 // output startup message and copyright to STDERR 2033 System.err.println( 2034 Messages.get().getBundle().key( 2035 Messages.LOG_STARTUP_CONSOLE_NOTE_2, 2036 OpenCms.getSystemInfo().getVersionNumber(), 2037 getSystemInfo().getWebApplicationName())); 2038 for (int i = 0; i < Messages.COPYRIGHT_BY_ALKACON.length; i++) { 2039 System.err.println(Messages.COPYRIGHT_BY_ALKACON[i]); 2040 } 2041 System.err.println(); 2042 2043 // initialize the configuration 2044 initConfiguration(configuration); 2045 } 2046 2047 /** 2048 * Initialize member variables.<p> 2049 */ 2050 protected void initMembers() { 2051 2052 synchronized (LOCK) { 2053 m_resourceInitHandlers = new ArrayList<I_CmsResourceInit>(); 2054 m_requestHandlers = new HashMap<String, I_CmsRequestHandler>(); 2055 m_systemInfo = new CmsSystemInfo(); 2056 m_exportPoints = Collections.emptySet(); 2057 m_defaultUsers = new CmsDefaultUsers(); 2058 m_localeManager = new CmsLocaleManager(Locale.ENGLISH); 2059 m_sessionManager = new CmsSessionManager(); 2060 m_runtimeProperties = new Hashtable<Object, Object>(); 2061 // the default event manager must be available because the configuration already registers events 2062 m_eventManager = new CmsEventManager(); 2063 // default link manager is required for test cases 2064 m_linkManager = new CmsLinkManager(new CmsDefaultLinkSubstitutionHandler()); 2065 } 2066 } 2067 2068 /** 2069 * Reads the requested resource from the OpenCms VFS, 2070 * in case a directory name is requested, the default files of the 2071 * directory will be looked up and the first match is returned.<p> 2072 * 2073 * The resource that is returned is always a <code>{@link org.opencms.file.CmsFile}</code>, 2074 * even though the content will usually not be loaded in the result. Folders are never returned since 2075 * the point of this method is really to load the default file if just a folder name is requested. If 2076 * there is no default file in a folder, then the return value is null and no CmsException is thrown.<p> 2077 * 2078 * The URI stored in the given OpenCms user context will be changed to the URI of the resource 2079 * that was found and returned.<p> 2080 * 2081 * Implementing and configuring an <code>{@link I_CmsResourceInit}</code> handler 2082 * allows to customize the process of default resource selection.<p> 2083 * 2084 * @param cms the current users OpenCms context 2085 * @param resourceName the path of the requested resource in the OpenCms VFS 2086 * @param req the current http request 2087 * @param res the current http response 2088 * 2089 * @return the requested resource read from the VFS 2090 * 2091 * @throws CmsException in case the requested file does not exist or the user has insufficient access permissions 2092 * 2093 * @see OpenCms#initResource(CmsObject, String, HttpServletRequest, HttpServletResponse) 2094 */ 2095 protected CmsResource initResource( 2096 CmsObject cms, 2097 String resourceName, 2098 HttpServletRequest req, 2099 HttpServletResponse res) 2100 throws CmsException { 2101 2102 CmsException tmpException = null; 2103 CmsResource resource; 2104 boolean handledSecure = false; 2105 2106 try { 2107 // try to read the requested resource 2108 resource = cms.readDefaultFile(resourceName, CmsResourceFilter.ignoreExpirationOffline(cms)); 2109 } catch (CmsException e) { 2110 // file or folder with given name does not exist, store exception 2111 tmpException = e; 2112 resource = null; 2113 } 2114 2115 if (resource != null) { 2116 // set the request uri to the right file 2117 cms.getRequestContext().setUri(cms.getSitePath(resource)); 2118 // test if this file is only available for internal access operations 2119 if (resource.isInternalOrInInternalFolder()) { 2120 throw new CmsException( 2121 Messages.get().container(Messages.ERR_READ_INTERNAL_RESOURCE_1, cms.getRequestContext().getUri())); 2122 } 2123 2124 resource = handleSecureResource(cms, req, res, resource, resourceName); 2125 if (resource == null) { 2126 handledSecure = true; 2127 2128 } 2129 } 2130 2131 boolean clearErrors = false; 2132 // test if this file has to be checked or modified 2133 for (I_CmsResourceInit handler : m_resourceInitHandlers) { 2134 try { 2135 resource = handler.initResource(resource, cms, req, res); 2136 // the loop has to be interrupted when the exception is thrown! 2137 } catch (CmsResourceInitException e) { 2138 if (e.isClearErrors()) { 2139 tmpException = null; 2140 clearErrors = true; 2141 } 2142 break; 2143 } catch (CmsSecurityException e) { 2144 tmpException = e; 2145 break; 2146 } 2147 } 2148 2149 // file is still null and not found exception was thrown, so throw original exception 2150 if (resource == null) { 2151 if (tmpException != null) { 2152 throw tmpException; 2153 } else if (!clearErrors) { 2154 throw new CmsVfsResourceNotFoundException( 2155 org.opencms.main.Messages.get().container( 2156 org.opencms.main.Messages.ERR_PATH_NOT_FOUND_1, 2157 resourceName)); 2158 2159 } 2160 } else { 2161 if (!handledSecure) { 2162 if (cms.getRequestContext().getDetailContentId() != null) { 2163 // in theory we should do this for all kinds of resource init handlers, 2164 // but I'm not clear on how to handle this in general, so only do this for detail pages for now 2165 resource = handleSecureResource(cms, req, res, resource, resourceName); 2166 handledSecure = true; 2167 } 2168 } 2169 } 2170 2171 // return the resource read from the VFS 2172 return resource; 2173 } 2174 2175 /** 2176 * Initializes the system with the OpenCms servlet.<p> 2177 * 2178 * This is the final step that is called on the servlets "init()" method. 2179 * It registers the servlets request handler and also outputs the final 2180 * startup message. The servlet should auto-load since the <code><load-on-startup></code> 2181 * parameter is set in the 'web.xml' by default.<p> 2182 * 2183 * @param servlet the OpenCms servlet 2184 */ 2185 protected void initServlet(OpenCmsServlet servlet) { 2186 2187 synchronized (LOCK) { 2188 // add the servlets request handler 2189 addRequestHandler(servlet); 2190 2191 // output the final 'startup is finished' message 2192 if (CmsLog.INIT.isInfoEnabled()) { 2193 CmsLog.INIT.info( 2194 Messages.get().getBundle().key( 2195 Messages.INIT_SYSTEM_RUNNING_1, 2196 CmsStringUtil.formatRuntime(getSystemInfo().getRuntime()))); 2197 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LINE_0)); 2198 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 2199 } 2200 } 2201 } 2202 2203 /** 2204 * Handler for built-in AJAX services that don't belong anywhere else and don't deserve their own request handler. 2205 * 2206 * @param remainingPath the remainder of the path after /handleBuiltinService 2207 * @param req the current request 2208 * @param res the current response 2209 * 2210 * @throws ServletException if something goes wrong 2211 */ 2212 protected void invokeBuiltinService(String remainingPath, HttpServletRequest req, HttpServletResponse res) 2213 throws ServletException { 2214 2215 try { 2216 CmsObject cms = initCmsObject(req, res); 2217 if (CmsGwtConstants.HANDLER_UNLOCK_PAGE.equals(remainingPath)) { 2218 CmsContainerpageService.unlockPage(cms, req, res); 2219 } else if (CmsGwtConstants.HANDLER_UPDATE_SESSION.equals(remainingPath)) { 2220 // Count this as a heartbeat request, because it's not caused by user activity 2221 boolean isHeartbeatRequest = true; 2222 OpenCms.getSessionManager().updateSessionInfo(cms, req, isHeartbeatRequest); 2223 } else if (remainingPath.startsWith(CmsGwtConstants.UNLOCK_FILE_PREFIX)) { 2224 String idStr = remainingPath.substring(CmsGwtConstants.UNLOCK_FILE_PREFIX.length()); 2225 try { 2226 cms.unlockResource(cms.readResource(new CmsUUID(idStr), CmsResourceFilter.ALL)); 2227 } catch (Exception e) { 2228 LOG.debug(e.getLocalizedMessage(), e); 2229 } 2230 } 2231 } catch (Exception e) { 2232 LOG.error(e.getLocalizedMessage(), e); 2233 throw new ServletException(e); 2234 } 2235 } 2236 2237 /** 2238 * Invokes the GWT servlet from within OpenCms.<p> 2239 * 2240 * @param serviceName the GWT PRC service class name 2241 * @param req the current servlet request 2242 * @param res the current servlet response 2243 * @param servletConfig the servlet configuration 2244 */ 2245 protected void invokeGwtService( 2246 String serviceName, 2247 HttpServletRequest req, 2248 HttpServletResponse res, 2249 ServletConfig servletConfig) { 2250 2251 CmsObject cms = null; 2252 try { 2253 // instantiate CMS context 2254 cms = initCmsObject(req, res); 2255 // instantiate GWT RPC service 2256 CmsGwtService rpcService = getGwtService(serviceName, servletConfig); 2257 // check permissions 2258 rpcService.checkPermissions(cms); 2259 String rpcContextStr = req.getHeader("X-OcmsRpcContext"); 2260 if (rpcContextStr == null) { 2261 rpcContextStr = "{}"; 2262 } 2263 // This makes the container page uri available in all RPC calls originating from the container page editor 2264 JSONObject rpcContext = new JSONObject(rpcContextStr); 2265 String pageIdStr = rpcContext.optString(CmsGwtConstants.RpcContext.PAGE_ID); 2266 CmsResource page = null; 2267 if (CmsUUID.isValidUUID(pageIdStr)) { 2268 try { 2269 page = cms.readResource(new CmsUUID(pageIdStr), CmsResourceFilter.IGNORE_EXPIRATION); 2270 } catch (Exception e) { 2271 LOG.error("Page id " + pageIdStr + " is unreadable: " + e.getLocalizedMessage(), e); 2272 } 2273 } 2274 if (page != null) { 2275 cms.getRequestContext().setUri(cms.getSitePath(page)); 2276 cms.getRequestContext().setAttribute(CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH, page.getRootPath()); 2277 } 2278 2279 // set runtime variables 2280 rpcService.setCms(cms); 2281 Object lock = req.getSession(); 2282 if (lock == null) { 2283 lock = new Object(); 2284 } 2285 rpcService.service(req, res); 2286 m_sessionManager.updateSessionInfo(cms, req, rpcService.isBroadcastCall()); 2287 } catch (CmsRoleViolationException rv) { 2288 // don't log these into the error channel 2289 LOG.debug(rv.getLocalizedMessage(), rv); 2290 // error code not set - set "unauthorized error" (401) 2291 int status = HttpServletResponse.SC_UNAUTHORIZED; 2292 res.setStatus(status); 2293 try { 2294 res.sendError(status, rv.toString()); 2295 } catch (IOException e) { 2296 // can be ignored 2297 LOG.error(e.getLocalizedMessage(), e); 2298 } 2299 } catch (Throwable t) { 2300 // error code not set - set "internal server error" (500) 2301 LOG.error(t.getLocalizedMessage(), t); 2302 int status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 2303 res.setStatus(status); 2304 try { 2305 res.sendError(status, t.toString()); 2306 } catch (IOException e) { 2307 // can be ignored 2308 LOG.error(e.getLocalizedMessage(), e); 2309 } 2310 } 2311 } 2312 2313 /** 2314 * This method adds an Object to the OpenCms runtime properties. 2315 * The runtime properties can be used to store Objects that are shared 2316 * in the whole system.<p> 2317 * 2318 * @param key the key to add the Object with 2319 * @param value the value of the Object to add 2320 */ 2321 protected void setRuntimeProperty(Object key, Object value) { 2322 2323 m_runtimeProperties.put(key, value); 2324 } 2325 2326 /** 2327 * Displays a resource from the OpenCms by writing the result to the provided 2328 * Servlet response output stream.<p> 2329 * 2330 * @param req the current servlet request 2331 * @param res the current servlet response 2332 */ 2333 protected void showResource(HttpServletRequest req, HttpServletResponse res) { 2334 2335 CmsObject cms = null; 2336 try { 2337 cms = initCmsObject(req, res); 2338 Map<String, String> logInfo = new HashMap<>(); 2339 logInfo.put("cms_siteroot", cms.getRequestContext().getSiteRoot()); 2340 logInfo.put("cms_project", cms.getRequestContext().getCurrentProject().getName()); 2341 try (CloseableThreadContext.Instance threadContext = CloseableThreadContext.putAll(logInfo)) { 2342 LOG.info("Updating log context: " + logInfo); 2343 String uri = cms.getRequestContext().getUri(); 2344 if (cms.getRequestContext().getCurrentProject().isOnlineProject()) { 2345 2346 if (uri.startsWith(CmsWorkplace.VFS_PATH_SITES)) { 2347 // resources within the sites folder may only be called with their site relative path 2348 // this should prevent showing pages from other sites with their root path 2349 throw new CmsVfsResourceNotFoundException( 2350 org.opencms.main.Messages.get().container( 2351 org.opencms.main.Messages.ERR_PATH_NOT_FOUND_1, 2352 uri)); 2353 } 2354 if (OpenCms.getStaticExportManager().isExportLink(cms, uri)) { 2355 // if we used the request's query string for getRfsName, clients could cause an unlimited number 2356 // of files to be exported just by varying the request parameters! 2357 String url = m_linkManager.getOnlineLink(cms, uri); 2358 res.sendRedirect(url); 2359 return; 2360 } 2361 } 2362 List<CmsSiteMatcher> currentSiteAliases = m_siteManager.getCurrentSite(cms).getAliases(); 2363 CmsSiteMatcher currentSiteMatcher = cms.getRequestContext().getRequestMatcher(); 2364 if (currentSiteAliases.contains(currentSiteMatcher.forDifferentScheme("http")) 2365 || currentSiteAliases.contains(currentSiteMatcher.forDifferentScheme("https"))) { 2366 int pos = currentSiteAliases.indexOf(currentSiteMatcher.forDifferentScheme("http")); 2367 if (pos == -1) { 2368 pos = currentSiteAliases.indexOf(currentSiteMatcher.forDifferentScheme("https")); 2369 } 2370 switch (currentSiteAliases.get(pos).getRedirectMode()) { 2371 case none: 2372 break; 2373 case temporary: 2374 res.sendRedirect( 2375 m_siteManager.getCurrentSite(cms).getUrl() + req.getContextPath() + req.getPathInfo()); 2376 return; 2377 case permanent: 2378 res.setHeader( 2379 CmsRequestUtil.HEADER_LOCATION, 2380 m_siteManager.getCurrentSite(cms).getUrl() + req.getContextPath() + req.getPathInfo()); 2381 res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 2382 return; 2383 default: 2384 break; 2385 } 2386 } 2387 2388 // user is initialized, now deliver the requested resource 2389 CmsResource resource = initResource(cms, cms.getRequestContext().getUri(), req, res); 2390 2391 // a resource init handler may use its own authentication, but return a resource to be loaded instead of handling the complete request processing by itself. 2392 // For this case, a request context attribute is used to pass the CmsObject that should be used for loading the resource. 2393 2394 Object alternativeCmsObject = cms.getRequestContext().removeAttribute( 2395 I_CmsResourceInit.ATTR_ALTERNATIVE_CMS_OBJECT); 2396 CmsObject cmsForLoad = cms; 2397 if (alternativeCmsObject instanceof CmsObject) { 2398 // we know it's not null at this point 2399 cmsForLoad = (CmsObject)alternativeCmsObject; 2400 } 2401 if (resource != null) { 2402 boolean forceAbsoluteLinks = checkForceAbsoluteLinks(req, cms, resource); 2403 cms.getRequestContext().setForceAbsoluteLinks(forceAbsoluteLinks); 2404 2405 // a file was read, go on process it 2406 m_resourceManager.loadResource(cmsForLoad, resource, req, res); 2407 if (cmsForLoad == cms) { 2408 // if we used a different CmsObject, we don't want to update the session with either 2409 // CmsObject - it's not necessary to do it for the original CmsObject, and using the alternative CmsObject 2410 // if there is already a session would switch the session user to the one of that CmsObject. We don't 2411 // want that, since the primary use case for the alternative CmsObject mechanism is 'stateless' authentication 2412 // for resource init handlers. 2413 m_sessionManager.updateSessionInfo(cms, req); 2414 } 2415 } 2416 } 2417 2418 } catch ( 2419 2420 Throwable t) { 2421 errorHandling(cms, req, res, t); 2422 } 2423 } 2424 2425 /** 2426 * Destroys this OpenCms instance, called if the servlet (or shell) is shut down.<p> 2427 */ 2428 protected void shutDown() { 2429 2430 synchronized (LOCK) { 2431 if (getRunLevel() > OpenCms.RUNLEVEL_0_OFFLINE) { 2432 System.err.println( 2433 Messages.get().getBundle().key( 2434 Messages.LOG_SHUTDOWN_CONSOLE_NOTE_2, 2435 getSystemInfo().getVersionNumber(), 2436 getSystemInfo().getWebApplicationName())); 2437 if (CmsLog.INIT.isInfoEnabled()) { 2438 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 2439 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 2440 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LINE_0)); 2441 CmsLog.INIT.info( 2442 Messages.get().getBundle().key( 2443 Messages.INIT_SHUTDOWN_START_1, 2444 getSystemInfo().getVersionNumber() + " [" + getSystemInfo().getVersionId() + "]")); 2445 CmsLog.INIT.info( 2446 Messages.get().getBundle().key( 2447 Messages.INIT_CURRENT_RUNLEVEL_1, 2448 Integer.valueOf(getRunLevel()))); 2449 CmsLog.INIT.info( 2450 Messages.get().getBundle().key( 2451 Messages.INIT_SHUTDOWN_TIME_1, 2452 new Date(System.currentTimeMillis()))); 2453 } 2454 2455 // take the system offline 2456 setRunLevel(OpenCms.RUNLEVEL_0_OFFLINE); 2457 2458 if (LOG.isDebugEnabled()) { 2459 // log exception to see which method did call the shutdown 2460 LOG.debug(Messages.get().getBundle().key(Messages.LOG_SHUTDOWN_TRACE_0), new Exception()); 2461 } 2462 2463 for (Runnable action : m_shutdownActions) { 2464 try { 2465 action.run(); 2466 } catch (Exception e) { 2467 CmsLog.INIT.error(e.getLocalizedMessage()); 2468 } 2469 } 2470 2471 for (I_CmsStartStopHandler handler : m_startStopHandlers) { 2472 try { 2473 handler.shutdown(); 2474 } catch (Throwable e) { 2475 CmsLog.INIT.error(e.getLocalizedMessage(), e); 2476 } 2477 } 2478 2479 try { 2480 // the first thing we have to do is to wait until the current publish process finishes 2481 if (null != m_publishEngine) { 2482 m_publishEngine.shutDown(); 2483 } 2484 } catch (Throwable e) { 2485 CmsLog.INIT.error( 2486 Messages.get().getBundle().key(Messages.LOG_ERROR_PUBLISH_SHUTDOWN_1, e.getMessage()), 2487 e); 2488 } 2489 try { 2490 // search manager must be shut down early since there may be background indexing still ongoing 2491 if (m_searchManager != null) { 2492 m_searchManager.shutDown(); 2493 } 2494 } catch (Throwable e) { 2495 CmsLog.INIT.error( 2496 Messages.get().getBundle().key(Messages.LOG_ERROR_SEARCH_MANAGER_SHUTDOWN_1, e.getMessage()), 2497 e); 2498 } 2499 try { 2500 // remote shell server must be shut down early since there is a background thread ongoing that reloads from the VFS 2501 if (m_remoteShellServer != null) { 2502 m_remoteShellServer.shutDown(); 2503 } 2504 } catch (Throwable e) { 2505 CmsLog.INIT.error( 2506 Messages.get().getBundle().key(Messages.LOG_ERROR_REMOTESHELL_SHUTDOWN_1, e.getMessage()), 2507 e); 2508 } 2509 try { 2510 // VFS bundle manager must be shut down early since there is a background thread ongoing that reloads from the VFS 2511 if (m_vfsBundleManager != null) { 2512 m_vfsBundleManager.shutDown(); 2513 } 2514 } catch (Throwable e) { 2515 CmsLog.INIT.error( 2516 Messages.get().getBundle().key(Messages.LOG_ERROR_VFSBUNDLE_MANAGER_SHUTDOWN_1, e.getMessage()), 2517 e); 2518 } 2519 try { 2520 if (m_staticExportManager != null) { 2521 m_staticExportManager.shutDown(); 2522 } 2523 } catch (Throwable e) { 2524 CmsLog.INIT.error( 2525 Messages.get().getBundle().key(Messages.LOG_ERROR_EXPORT_SHUTDOWN_1, e.getMessage()), 2526 e); 2527 } 2528 try { 2529 if (m_moduleManager != null) { 2530 m_moduleManager.shutDown(); 2531 } 2532 } catch (Throwable e) { 2533 CmsLog.INIT.error( 2534 Messages.get().getBundle().key(Messages.LOG_ERROR_MODULE_SHUTDOWN_1, e.getMessage()), 2535 e); 2536 } 2537 2538 try { 2539 if (m_executor != null) { 2540 m_executor.shutdown(); 2541 m_executor.awaitTermination(30, TimeUnit.SECONDS); 2542 } 2543 } catch (Throwable e) { 2544 CmsLog.INIT.error( 2545 Messages.get().getBundle().key(Messages.LOG_ERROR_MODULE_SHUTDOWN_1, e.getMessage()), 2546 e); 2547 } 2548 2549 try { 2550 if (m_scheduleManager != null) { 2551 m_scheduleManager.shutDown(); 2552 } 2553 } catch (Throwable e) { 2554 CmsLog.INIT.error( 2555 Messages.get().getBundle().key(Messages.LOG_ERROR_SCHEDULE_SHUTDOWN_1, e.getMessage()), 2556 e); 2557 } 2558 try { 2559 if (m_resourceManager != null) { 2560 m_resourceManager.shutDown(); 2561 } 2562 } catch (Throwable e) { 2563 CmsLog.INIT.error( 2564 Messages.get().getBundle().key(Messages.LOG_ERROR_RESOURCE_SHUTDOWN_1, e.getMessage()), 2565 e); 2566 } 2567 2568 try { 2569 if (m_repositoryManager != null) { 2570 m_repositoryManager.shutDown(); 2571 } 2572 } catch (Throwable e) { 2573 CmsLog.INIT.error(e.getLocalizedMessage(), e); 2574 } 2575 2576 try { 2577 // has to be stopped before the security manager, since this thread uses it 2578 if (m_threadStore != null) { 2579 m_threadStore.shutDown(); 2580 } 2581 } catch (Throwable e) { 2582 CmsLog.INIT.error( 2583 Messages.get().getBundle().key(Messages.LOG_ERROR_THREAD_SHUTDOWN_1, e.getMessage()), 2584 e); 2585 } 2586 try { 2587 if (m_securityManager != null) { 2588 m_securityManager.destroy(); 2589 } 2590 } catch (Throwable e) { 2591 CmsLog.INIT.error( 2592 Messages.get().getBundle().key(Messages.LOG_ERROR_SECURITY_SHUTDOWN_1, e.getMessage()), 2593 e); 2594 } 2595 try { 2596 if (m_sessionManager != null) { 2597 m_sessionManager.shutdown(); 2598 } 2599 } catch (Throwable e) { 2600 CmsLog.INIT.error( 2601 Messages.get().getBundle().key(Messages.LOG_ERROR_SESSION_MANAGER_SHUTDOWN_1, e.getMessage()), 2602 e); 2603 } 2604 try { 2605 if (m_memoryMonitor != null) { 2606 m_memoryMonitor.shutdown(); 2607 } 2608 } catch (Throwable e) { 2609 CmsLog.INIT.error( 2610 Messages.get().getBundle().key(Messages.LOG_ERROR_MEMORY_MONITOR_SHUTDOWN_1, e.getMessage()), 2611 e); 2612 } 2613 try { 2614 if (m_adeManager != null) { 2615 m_adeManager.shutdown(); 2616 } 2617 } catch (Throwable e) { 2618 CmsLog.INIT.error( 2619 Messages.get().getBundle().key(Messages.LOG_ERROR_ADE_MANAGER_SHUTDOWN_1, e.getMessage()), 2620 e); 2621 } 2622 2623 String runtime = CmsStringUtil.formatRuntime(getSystemInfo().getRuntime()); 2624 if (CmsLog.INIT.isInfoEnabled()) { 2625 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_OPENCMS_STOPPED_1, runtime)); 2626 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_LINE_0)); 2627 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 2628 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DOT_0)); 2629 } 2630 System.err.println(Messages.get().getBundle().key(Messages.LOG_CONSOLE_TOTAL_RUNTIME_1, runtime)); 2631 2632 } 2633 try { 2634 final javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); 2635 final javax.management.ObjectName mxbeanName = new javax.management.ObjectName( 2636 "org.opencms.mx:type=CmsDiagnosticsMXBean"); 2637 if (mbs.isRegistered(mxbeanName)) { 2638 mbs.unregisterMBean(mxbeanName); 2639 } 2640 } catch (Throwable e) { 2641 CmsLog.INIT.error(e.getLocalizedMessage(), e); 2642 } 2643 m_instance = null; 2644 } 2645 } 2646 2647 /** 2648 * This method updates the request context information.<p> 2649 * 2650 * The update information is:<br> 2651 * <ul> 2652 * <li>Requested Url</li> 2653 * <li>Locale</li> 2654 * <li>Encoding</li> 2655 * <li>Remote Address</li> 2656 * <li>Request Time</li> 2657 * </ul> 2658 * 2659 * @param request the current request 2660 * @param cms the cms object to update the request context for 2661 * 2662 * @return a new updated cms context 2663 * 2664 * @throws CmsException if something goes wrong 2665 */ 2666 protected CmsObject updateContext(HttpServletRequest request, CmsObject cms) throws CmsException { 2667 2668 // get the right site for the request 2669 String siteRoot = null; 2670 boolean isWorkplace = cms.getRequestContext().getUri().startsWith("/system/workplace/") 2671 || request.getRequestURI().startsWith(OpenCms.getSystemInfo().getWorkplaceContext()); 2672 if (isWorkplace && getRoleManager().hasRole(cms, CmsRole.ELEMENT_AUTHOR)) { 2673 // keep the site root for workplace requests 2674 siteRoot = cms.getRequestContext().getSiteRoot(); 2675 } else { 2676 CmsSite site = OpenCms.getSiteManager().matchRequest(request); 2677 siteRoot = site.getSiteRoot(); 2678 } 2679 return initCmsObject( 2680 request, 2681 cms.getRequestContext().getCurrentUser(), 2682 siteRoot, 2683 cms.getRequestContext().getCurrentProject().getUuid(), 2684 cms.getRequestContext().getOuFqn()); 2685 } 2686 2687 /** 2688 * Upgrades to runlevel {@link OpenCms#RUNLEVEL_3_SHELL_ACCESS}, 2689 * this is shell access to the database but no Servlet context.<p> 2690 * 2691 * To upgrade the runlevel, the system must be in runlevel {@link OpenCms#RUNLEVEL_1_CORE_OBJECT}, 2692 * otherwise an exception is thrown.<p> 2693 * 2694 * @param configuration the configuration 2695 * @throws CmsInitException in case OpenCms can not be initialized 2696 * @return the initialized OpenCmsCore 2697 */ 2698 protected OpenCmsCore upgradeRunlevel(CmsParameterConfiguration configuration) throws CmsInitException { 2699 2700 synchronized (LOCK) { 2701 if ((m_instance != null) && (getRunLevel() >= OpenCms.RUNLEVEL_2_INITIALIZING)) { 2702 // instance already in runlevel 3 or 4 2703 return m_instance; 2704 } 2705 if (getRunLevel() != OpenCms.RUNLEVEL_1_CORE_OBJECT) { 2706 CmsLog.INIT.error( 2707 Messages.get().getBundle().key( 2708 Messages.LOG_WRONG_INIT_SEQUENCE_2, 2709 Integer.valueOf(3), 2710 Integer.valueOf(getRunLevel()))); 2711 return m_instance; 2712 } 2713 2714 // set the runlevel to "initializing OpenCms" 2715 setRunLevel(OpenCms.RUNLEVEL_2_INITIALIZING); 2716 // initialize the configuration 2717 m_instance.initConfiguration(configuration); 2718 // upgrade the runlevel - OpenCms shell is available 2719 setRunLevel(OpenCms.RUNLEVEL_3_SHELL_ACCESS); 2720 2721 afterUpgradeRunlevel(); 2722 2723 return m_instance; 2724 } 2725 } 2726 2727 /** 2728 * Upgrades to runlevel {@link OpenCms#RUNLEVEL_4_SERVLET_ACCESS}, 2729 * this is the final runlevel with an initialized database and Servlet context.<p> 2730 * 2731 * To upgrade the runlevel, the system must be in runlevel {@link OpenCms#RUNLEVEL_1_CORE_OBJECT}, 2732 * otherwise an exception is thrown.<p> 2733 * 2734 * @param context the current servlet context 2735 * @throws CmsInitException in case OpenCms can not be initialized 2736 * @return the initialized OpenCmsCore 2737 */ 2738 protected OpenCmsCore upgradeRunlevel(ServletContext context) throws CmsInitException { 2739 2740 synchronized (LOCK) { 2741 if ((m_instance != null) && (getRunLevel() >= OpenCms.RUNLEVEL_4_SERVLET_ACCESS)) { 2742 // instance already in runlevel 5 or 6 2743 return m_instance; 2744 } 2745 if (getRunLevel() != OpenCms.RUNLEVEL_1_CORE_OBJECT) { 2746 CmsLog.INIT.error( 2747 Messages.get().getBundle().key( 2748 Messages.LOG_WRONG_INIT_SEQUENCE_2, 2749 Integer.valueOf(4), 2750 Integer.valueOf(getRunLevel()))); 2751 return m_instance; 2752 } 2753 2754 // set the runlevel to "initializing OpenCms" 2755 setRunLevel(OpenCms.RUNLEVEL_2_INITIALIZING); 2756 // initialize the servlet context 2757 m_instance.initContext(context); 2758 // initialization successfully finished - OpenCms servlet is online 2759 // the runlevel will change from 2 directly to 4, this is on purpose 2760 setRunLevel(OpenCms.RUNLEVEL_4_SERVLET_ACCESS); 2761 2762 afterUpgradeRunlevel(); 2763 return m_instance; 2764 } 2765 } 2766 2767 /** 2768 * Writes the XML configuration for the provided configuration class.<p> 2769 * 2770 * @param clazz the configuration class to write the XML for 2771 */ 2772 protected void writeConfiguration(Class<?> clazz) { 2773 2774 // exception handling is provided here to ensure identical log messages 2775 try { 2776 m_configurationManager.writeConfiguration(clazz); 2777 } catch (IOException e) { 2778 CmsLog.getLog(CmsConfigurationManager.class).error( 2779 Messages.get().getBundle().key(Messages.LOG_ERROR_WRITING_CONFIG_1, clazz.getName()), 2780 e); 2781 } catch (CmsConfigurationException e) { 2782 CmsLog.getLog(CmsConfigurationManager.class).error( 2783 Messages.get().getBundle().key(Messages.LOG_ERROR_WRITING_CONFIG_1, clazz.getName()), 2784 e); 2785 } 2786 } 2787 2788 /** 2789 * Adds the given set of export points to the list of all configured export points.<p> 2790 * 2791 * @param exportPoints the export points to add 2792 */ 2793 private void addExportPoints(Set<CmsExportPoint> exportPoints) { 2794 2795 // create a new immutable set of export points 2796 HashSet<CmsExportPoint> newSet = new HashSet<CmsExportPoint>(m_exportPoints.size() + exportPoints.size()); 2797 newSet.addAll(exportPoints); 2798 newSet.addAll(m_exportPoints); 2799 m_exportPoints = Collections.unmodifiableSet(newSet); 2800 } 2801 2802 /** 2803 * Finishes the startup sequence after last runlevel upgrade.<p> 2804 */ 2805 private void afterUpgradeRunlevel() { 2806 2807 try { 2808 // read the persistent locks 2809 m_instance.m_securityManager.readLocks(); 2810 } catch (CmsException e) { 2811 if (LOG.isErrorEnabled()) { 2812 LOG.error( 2813 org.opencms.lock.Messages.get().getBundle().key(org.opencms.lock.Messages.ERR_READ_LOCKS_0), 2814 e); 2815 } 2816 } 2817 2818 if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_4_SERVLET_ACCESS) { 2819 // only init ADE manager in case of servlet initialization, it won't be needed in case of shell access 2820 CmsThreadStatsTreeProfilingHandler stats = new CmsThreadStatsTreeProfilingHandler(); 2821 try { 2822 CmsDefaultProfilingHandler.INSTANCE.addHandler(stats); 2823 m_adeManager.initialize(); 2824 } finally { 2825 CmsDefaultProfilingHandler.INSTANCE.removeHandler(stats); 2826 if (stats.hasData()) { 2827 String adeInitData = stats.dump(); 2828 String prefix = String.format("%010X", Long.valueOf(System.currentTimeMillis() / 1000)); 2829 String path = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf( 2830 "logs/" + prefix + "_startup-ade-driver-report.xml"); 2831 try (FileOutputStream out = new FileOutputStream(path)) { 2832 out.write(adeInitData.getBytes("UTF-8")); 2833 } catch (Exception e) { 2834 LOG.error( 2835 "Could not write ADE init profiling data to file, writing to log instead: " 2836 + e.getLocalizedMessage(), 2837 e); 2838 LOG.error(adeInitData); 2839 } 2840 } 2841 } 2842 2843 try { 2844 // get an Admin cms context object with site root set to "/" 2845 CmsObject adminCms = initCmsObject( 2846 null, 2847 null, 2848 getDefaultUsers().getUserAdmin(), 2849 (String)null, 2850 (String)null); 2851 OpenCms.getSearchManager().initSpellcheckIndex(adminCms); 2852 } catch (CmsException e) { 2853 throw new CmsInitException(Messages.get().container(Messages.ERR_CRITICAL_INIT_ADMINCMS_0), e); 2854 } 2855 } 2856 2857 try { 2858 m_folderSizeTrackerFuture = m_executor.submit( 2859 () -> new CmsFolderSizeTracker(m_configAdminCms, false).initialize()); 2860 } catch (Exception e) { 2861 LOG.error(e.getLocalizedMessage(), e); 2862 } 2863 2864 try { 2865 m_onlineFolderSizeTrackerFuture = m_executor.submit( 2866 () -> new CmsFolderSizeTracker(m_configAdminCms, true).initialize()); 2867 } catch (Exception e) { 2868 LOG.error(e.getLocalizedMessage(), e); 2869 } 2870 2871 // everything is initialized, now start publishing 2872 m_publishManager.startPublishing(); 2873 2874 for (I_CmsStartStopHandler handler : ServiceLoader.load(I_CmsStartStopHandler.class)) { 2875 m_startStopHandlers.add(handler); 2876 } 2877 2878 for (I_CmsStartStopHandler handler : m_startStopHandlers) { 2879 try { 2880 handler.startup(m_configAdminCms); 2881 } catch (Exception e) { 2882 LOG.error(e.getLocalizedMessage(), e); 2883 } 2884 } 2885 2886 try { 2887 CmsDiagnosticsMXBean.register(m_configAdminCms); 2888 } catch (Throwable e) { 2889 CmsLog.INIT.error(e.getLocalizedMessage(), e); 2890 } 2891 2892 } 2893 2894 /** 2895 * Checks whether 'force absolute links' mode should be enabled in request context. 2896 * 2897 * @param req the current request 2898 * @param cms the CMS context 2899 * @param resource the resource to load 2900 * 2901 * @return true if 'force absolute links' mode should be enabled 2902 */ 2903 private boolean checkForceAbsoluteLinks(HttpServletRequest req, CmsObject cms, CmsResource resource) { 2904 2905 try { 2906 boolean forceAbsoluteLinks = Boolean.parseBoolean(req.getParameter(PARAM_FORCE_ABSOLUTE_LINKS)); 2907 if (forceAbsoluteLinks) { 2908 // only need to read the property if the request parameter is actually set 2909 CmsProperty enableForceAbsoluteProp = cms.readPropertyObject( 2910 resource, 2911 CmsPropertyDefinition.PROPERTY_LINKS_FORCEABSOLUTE_ENABLED, 2912 true); 2913 return Boolean.parseBoolean(enableForceAbsoluteProp.getValue()); 2914 } else { 2915 return false; 2916 } 2917 } catch (Exception e) { 2918 LOG.warn(e.getLocalizedMessage(), e); 2919 return false; 2920 } 2921 } 2922 2923 /** 2924 * This method performs the error handling for OpenCms.<p> 2925 * 2926 * @param cms the current cms context, might be null ! 2927 * @param req the client request 2928 * @param res the client response 2929 * @param t the exception that occurred 2930 */ 2931 private void errorHandling(CmsObject cms, HttpServletRequest req, HttpServletResponse res, Throwable t) { 2932 2933 // remove the controller attribute from the request 2934 CmsFlexController.removeController(req); 2935 req.removeAttribute(CmsJspStandardContextBean.ATTRIBUTE_NAME); 2936 2937 boolean canWrite = (!res.isCommitted() && !res.containsHeader("Location")); 2938 int status = -1; 2939 boolean isGuest = true; 2940 2941 if (t instanceof ServletException) { 2942 ServletException s = (ServletException)t; 2943 if (s.getRootCause() != null) { 2944 t = s.getRootCause(); 2945 } 2946 if (CmsJspLoader.isJasperCompilerException(t)) { 2947 LOG.error(t.getLocalizedMessage()); 2948 } else { 2949 LOG.error(t.getLocalizedMessage(), t); 2950 } 2951 } else if (t instanceof CmsSecurityException) { 2952 LOG.warn(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2953 // access error - display login dialog 2954 if (canWrite) { 2955 try { 2956 m_authorizationHandler.requestAuthorization(req, res, getLoginFormURL(req, res)); 2957 } catch (IOException ioe) { 2958 LOG.debug("Error calling authorization handler.", ioe); 2959 } 2960 return; 2961 } 2962 } else if (t instanceof CmsDbEntryNotFoundException) { 2963 LOG.warn(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2964 // user or group does not exist 2965 status = HttpServletResponse.SC_SERVICE_UNAVAILABLE; 2966 isGuest = false; 2967 } else if (t instanceof CmsVfsResourceNotFoundException) { 2968 LOG.warn(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2969 // file not found - display 404 error. 2970 status = HttpServletResponse.SC_NOT_FOUND; 2971 } else if (t instanceof CmsException) { 2972 LOG.error(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2973 if (t.getCause() != null) { 2974 t = t.getCause(); 2975 } 2976 } else if (t.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) { 2977 // only log to debug channel any exceptions caused by a client abort - this is tomcat specific 2978 LOG.debug(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2979 } else { 2980 LOG.error(t.getLocalizedMessage() + " rendering URL " + req.getRequestURL(), t); 2981 } 2982 2983 if (status < 1) { 2984 // error code not set - set "internal server error" (500) 2985 status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 2986 } 2987 res.setStatus(status); 2988 2989 try { 2990 if ((cms != null) && (cms.getRequestContext().getCurrentUser() != null)) { 2991 isGuest = isGuest 2992 && (cms.getRequestContext().getCurrentUser().isGuestUser() 2993 || cms.userInGroup( 2994 cms.getRequestContext().getCurrentUser().getName(), 2995 OpenCms.getDefaultUsers().getGroupGuests())); 2996 } 2997 } catch (CmsException e) { 2998 // result is false 2999 LOG.error(e.getLocalizedMessage(), e); 3000 } 3001 3002 if (canWrite) { 3003 res.setContentType("text/html"); 3004 CmsRequestUtil.setNoCacheHeaders(res); 3005 if ((status != 404) 3006 && !isGuest 3007 && (cms != null) 3008 && (!CmsJsonPartFilter.isJsonRequest(req)) 3009 && !cms.getRequestContext().getCurrentProject().isOnlineProject()) { 3010 try { 3011 res.setStatus(HttpServletResponse.SC_OK); 3012 res.getWriter().print(CmsErrorUI.getBootstrapPage(cms, t, req)); 3013 } catch (IOException e) { 3014 // can be ignored 3015 LOG.error(e.getLocalizedMessage(), e); 3016 } 3017 } else { 3018 try { 3019 res.sendError(status, t.toString()); 3020 } catch (IOException e) { 3021 // can be ignored 3022 LOG.error(e.getLocalizedMessage(), e); 3023 } 3024 } 3025 } 3026 } 3027 3028 /** 3029 * 3030 * 3031 * @param serviceName the GWT PRC service class name 3032 * @param servletConfig the servlet configuration 3033 * 3034 * @return the GWT service instance 3035 * 3036 * @throws Throwable if something goes wrong 3037 */ 3038 private synchronized CmsGwtService getGwtService(String serviceName, ServletConfig servletConfig) throws Throwable { 3039 3040 CmsGwtServiceContext2 context = m_gwtServiceContexts.get(serviceName); 3041 if (context == null) { 3042 context = new CmsGwtServiceContext2(serviceName); 3043 m_gwtServiceContexts.put(serviceName, context); 3044 } 3045 CmsGwtService gwtService = (CmsGwtService)Class.forName(serviceName).getDeclaredConstructor().newInstance(); 3046 gwtService.init(servletConfig); 3047 gwtService.setContext(context); 3048 return gwtService; 3049 } 3050 3051 /** 3052 * Reads the login form which should be used for authenticating the current request.<p> 3053 * 3054 * @param req current request 3055 * @param res current response 3056 * 3057 * @return the URL of the login form or <code>null</code> if not set 3058 * 3059 * @throws IOException in case of IO errors 3060 */ 3061 private String getLoginFormURL(HttpServletRequest req, HttpServletResponse res) throws IOException { 3062 3063 CmsHttpAuthenticationSettings httpAuthenticationSettings = OpenCms.getSystemInfo().getHttpAuthenticationSettings(); 3064 String loginFormURL = null; 3065 3066 // this will create an admin user with the "right" site root already set 3067 CmsObject adminCms; 3068 try { 3069 adminCms = initCmsObject(req, res, OpenCms.getDefaultUsers().getUserAdmin(), null, null); 3070 } catch (CmsException e) { 3071 // this should never happen, if it does we can't continue 3072 throw new IOException( 3073 Messages.get().getBundle().key( 3074 Messages.ERR_INVALID_INIT_USER_2, 3075 OpenCms.getDefaultUsers().getUserAdmin(), 3076 3077 null), 3078 e); 3079 } 3080 // get the requested resource 3081 String path = adminCms.getRequestContext().getUri(); 3082 CmsProperty propertyLoginForm = null; 3083 try { 3084 propertyLoginForm = adminCms.readPropertyObject(path, CmsPropertyDefinition.PROPERTY_LOGIN_FORM, true); 3085 } catch (Throwable t) { 3086 if (t instanceof CmsVfsResourceNotFoundException) { 3087 // if we can't read the property from the path, try to use the resource init handlers to find the 3088 // resource to read it from 3089 CmsResource alternativeResource = null; 3090 try { 3091 3092 try { 3093 // use null as the response to avoid side effects like redirects, etc. 3094 alternativeResource = initResource(adminCms, path, req, null); 3095 } catch (Exception e) { 3096 LOG.warn(e.getLocalizedMessage(), e); 3097 } 3098 if (alternativeResource != null) { 3099 propertyLoginForm = adminCms.readPropertyObject( 3100 adminCms.getSitePath(alternativeResource), 3101 CmsPropertyDefinition.PROPERTY_LOGIN_FORM, 3102 true); 3103 } 3104 } catch (Exception e) { 3105 LOG.error(e.getLocalizedMessage(), e); 3106 } 3107 } 3108 3109 if (propertyLoginForm == null) { 3110 if (LOG.isWarnEnabled()) { 3111 LOG.warn( 3112 Messages.get().getBundle().key( 3113 Messages.LOG_ERROR_READING_AUTH_PROP_2, 3114 CmsPropertyDefinition.PROPERTY_LOGIN_FORM, 3115 path), 3116 t); 3117 } 3118 3119 } 3120 } 3121 3122 String params = null; 3123 if ((propertyLoginForm != null) 3124 && (propertyLoginForm != CmsProperty.getNullProperty()) 3125 && CmsStringUtil.isNotEmpty(propertyLoginForm.getValue())) { 3126 // login form property value was found 3127 // build a redirect URL using the value of the property 3128 // "__loginform" is a dummy request parameter that could be used in a JSP template to trigger 3129 // if the template should display a login formular or not 3130 loginFormURL = propertyLoginForm.getValue(); 3131 params = "__loginform=true"; 3132 } else if (!httpAuthenticationSettings.useBrowserBasedHttpAuthentication() 3133 && CmsStringUtil.isNotEmpty(httpAuthenticationSettings.getFormBasedHttpAuthenticationUri())) { 3134 // login form property value not set, but form login set in configuration 3135 // build a redirect URL to the default login form URI configured in opencms.properties 3136 loginFormURL = httpAuthenticationSettings.getFormBasedHttpAuthenticationUri(); 3137 } 3138 3139 String callbackURL = CmsRequestUtil.encodeParamsWithUri(path, req); 3140 if (loginFormURL != null) { 3141 if (!loginFormURL.startsWith("http")) { 3142 loginFormURL = m_linkManager.substituteLink(adminCms, loginFormURL, null, true); 3143 } else { 3144 callbackURL = m_linkManager.getServerLink(adminCms, path); 3145 callbackURL = CmsRequestUtil.encodeParamsWithUri(callbackURL, req); 3146 } 3147 } 3148 3149 return m_authorizationHandler.getLoginFormURL(loginFormURL, params, callbackURL); 3150 } 3151 3152 /** 3153 * If we are in the Online project, check if the given resource is marked as secure, and handle it according to the secure server configuration.<p> 3154 * 3155 * @param cms the current CMS context 3156 * @param req the current request 3157 * @param res the current response 3158 * @param resource the resource to check 3159 * @param resourceName the resource path from the request 3160 * 3161 * @return the resource to replace the original resource 3162 * 3163 * @throws CmsException if something goes wrong 3164 * @throws CmsVfsResourceNotFoundException if the resource could not be found 3165 */ 3166 private CmsResource handleSecureResource( 3167 CmsObject cms, 3168 HttpServletRequest req, 3169 HttpServletResponse res, 3170 CmsResource resource, 3171 String resourceName) 3172 throws CmsException, CmsVfsResourceNotFoundException { 3173 3174 // check online project 3175 if (cms.getRequestContext().getCurrentProject().isOnlineProject() && (res != null)) { 3176 boolean secure = false; 3177 try { 3178 // check if resource is secure 3179 secure = Boolean.valueOf( 3180 cms.readPropertyObject( 3181 cms.getSitePath(resource), 3182 CmsPropertyDefinition.PROPERTY_SECURE, 3183 true).getValue()).booleanValue(); 3184 } catch (CmsVfsResourceNotFoundException e) { 3185 LOG.warn(e.getLocalizedMessage(), e); 3186 } catch (CmsException e) { 3187 LOG.error(e.getLocalizedMessage(), e); 3188 } 3189 if (secure) { 3190 CmsResource resource1 = resource; 3191 // resource is secure, check site config 3192 CmsSite site = OpenCms.getSiteManager().getCurrentSite(cms); 3193 // check the secure url 3194 String secureUrl = null; 3195 try { 3196 secureUrl = site.getSecureUrl(); 3197 } catch (Exception e) { 3198 LOG.error( 3199 Messages.get().getBundle().key(Messages.ERR_SECURE_SITE_NOT_CONFIGURED_1, resourceName), 3200 e); 3201 throw new CmsException( 3202 Messages.get().container(Messages.ERR_SECURE_SITE_NOT_CONFIGURED_1, resourceName), 3203 e); 3204 } 3205 boolean usingSec = true; 3206 if (req != null) { 3207 usingSec = req.getRequestURL().toString().toUpperCase().startsWith(secureUrl.toUpperCase()); 3208 } 3209 if (site.isExclusiveUrl() && !usingSec) { 3210 resource1 = null; 3211 // secure resource without secure protocol, check error config 3212 if (site.isExclusiveError()) { 3213 // trigger 404 error 3214 throw new CmsVfsResourceNotFoundException( 3215 Messages.get().container(Messages.ERR_REQUEST_SECURE_RESOURCE_0)); 3216 } else { 3217 // redirect 3218 String target = OpenCms.getLinkManager().getOnlineLink(cms, resourceName); 3219 if (!target.toLowerCase().startsWith(secureUrl.toLowerCase())) { 3220 Optional<String> targetWithReplacedHost = CmsStringUtil.replacePrefix( 3221 target, 3222 site.getSiteMatcher().getUrl(), 3223 secureUrl, 3224 true); 3225 if (targetWithReplacedHost.isPresent()) { 3226 target = targetWithReplacedHost.get(); 3227 } 3228 if (!target.toLowerCase().startsWith(secureUrl.toLowerCase())) { 3229 LOG.warn("Failed to generate secure URL for " + target + ", site = " + site); 3230 } 3231 } 3232 3233 try { 3234 if (site.usesPermanentRedirects()) { 3235 res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 3236 res.setHeader("Location", target); 3237 } else { 3238 res.sendRedirect(target); 3239 } 3240 } catch (Exception e) { 3241 // ignore, but should never happen 3242 LOG.error("Error sending secure resource redirect.", e); 3243 } 3244 } 3245 } 3246 resource = resource1; 3247 } 3248 3249 } 3250 return resource; 3251 } 3252 3253 /** 3254 * Initializes a CmsObject with the given context information.<p> 3255 * 3256 * @param contextInfo the information for the CmsObject context to create 3257 * 3258 * @return the initialized CmsObject 3259 * 3260 * @throws CmsException if something goes wrong 3261 */ 3262 private CmsObject initCmsObject(CmsContextInfo contextInfo) throws CmsException { 3263 3264 CmsUser user = contextInfo.getUser(); 3265 if (user == null) { 3266 user = m_securityManager.readUser(null, contextInfo.getUserName()); 3267 } 3268 3269 CmsProject project = contextInfo.getProject(); 3270 if (project == null) { 3271 project = m_securityManager.readProject(contextInfo.getProjectName()); 3272 } 3273 3274 // first create the request context 3275 CmsRequestContext context = new CmsRequestContext( 3276 user, 3277 project, 3278 contextInfo.getRequestedUri(), 3279 contextInfo.getRequestMatcher(), 3280 contextInfo.getSiteRoot(), 3281 contextInfo.isSecureRequest(), 3282 contextInfo.getLocale(), 3283 contextInfo.getEncoding(), 3284 contextInfo.getRemoteAddr(), 3285 contextInfo.getRequestTime(), 3286 m_resourceManager.getFolderTranslator(), 3287 m_resourceManager.getFileTranslator(), 3288 contextInfo.getOuFqn(), 3289 contextInfo.isForceAbsoluteLinks()); 3290 context.setDetailResource(contextInfo.getDetailResource()); 3291 3292 // now initialize and return the CmsObject 3293 return new CmsObject(m_securityManager, context); 3294 } 3295 3296 /** 3297 * Initializes a {@link CmsObject} with the given users information.<p> 3298 * 3299 * @param request the current http request (or <code>null</code>) 3300 * @param user the initialized user 3301 * @param siteRoot the users current site 3302 * @param projectId the id of the users current project 3303 * @param ouFqn the organizational unit 3304 * 3305 * @return the initialized CmsObject 3306 * 3307 * @throws CmsException in case something goes wrong 3308 */ 3309 private CmsObject initCmsObject( 3310 HttpServletRequest request, 3311 CmsUser user, 3312 String siteRoot, 3313 CmsUUID projectId, 3314 String ouFqn) 3315 throws CmsException { 3316 3317 CmsProject project = null; 3318 try { 3319 project = m_securityManager.readProject(projectId); 3320 } catch (CmsDbEntryNotFoundException e) { 3321 // project not found, switch to online project 3322 project = m_securityManager.readProject(CmsProject.ONLINE_PROJECT_ID); 3323 LOG.debug("Project '" + projectId + "' was not found, switch to online project.", e); 3324 } 3325 3326 // get requested resource uri and remote IP address, as well as time for "time warp" browsing 3327 String requestedResource = null; 3328 Long requestTimeAttr = null; 3329 String remoteAddr; 3330 CmsSiteMatcher requestMatcher; 3331 3332 boolean isSecureRequest = false; 3333 if (request != null) { 3334 // get path info from request 3335 requestedResource = getPathInfo(request); 3336 3337 // check for special header for remote address 3338 remoteAddr = request.getHeader(CmsRequestUtil.HEADER_X_FORWARDED_FOR); 3339 if (remoteAddr == null) { 3340 // if header is not available, use default remote address 3341 remoteAddr = request.getRemoteAddr(); 3342 } 3343 3344 // check for special "time warp" browsing 3345 HttpSession session = request.getSession(false); 3346 if (session != null) { 3347 // no new session must be created here 3348 requestTimeAttr = (Long)session.getAttribute(CmsContextInfo.ATTRIBUTE_REQUEST_TIME); 3349 } 3350 isSecureRequest = OpenCms.getSiteManager().usesSecureSite(request); 3351 3352 // create the request matcher 3353 requestMatcher = new CmsSiteMatcher(request.getRequestURL().toString()); 3354 3355 } else { 3356 // if no request is available, the IP is always set to localhost 3357 remoteAddr = CmsContextInfo.LOCALHOST; 3358 // also the request matcher is always the workplace server 3359 requestMatcher = OpenCms.getSiteManager().getWorkplaceSiteMatcher(); 3360 } 3361 if (requestedResource == null) { 3362 // path info can still be null 3363 requestedResource = "/"; 3364 } 3365 3366 // calculate the request time 3367 long requestTime; 3368 if (requestTimeAttr == null) { 3369 requestTime = System.currentTimeMillis(); 3370 } else { 3371 requestTime = requestTimeAttr.longValue(); 3372 } 3373 3374 // get locale and encoding 3375 CmsI18nInfo i18nInfo; 3376 if (m_localeManager.isInitialized()) { 3377 // locale manager is initialized 3378 // resolve locale and encoding 3379 if ((request != null) 3380 && (requestedResource.endsWith(OpenCmsServlet.HANDLE_GWT) || isWorkplaceServletRequest(request))) { 3381 // GWT RPC or workplace servlet call, always keep the request encoding and use the default locale 3382 i18nInfo = new CmsI18nInfo(CmsLocaleManager.getDefaultLocale(), request.getCharacterEncoding()); 3383 } else { 3384 String resourceName; 3385 if (requestedResource.startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { 3386 // add site root only if resource name does not start with "/system" 3387 resourceName = requestedResource; 3388 } else if (OpenCms.getSiteManager().startsWithShared(requestedResource)) { 3389 resourceName = requestedResource; 3390 } else { 3391 resourceName = siteRoot.concat(requestedResource); 3392 } 3393 i18nInfo = m_localeManager.getI18nInfo(request, user, project, resourceName); 3394 } 3395 } else { 3396 // locale manager not initialized, this will be true _only_ during system startup 3397 // the values set does not matter, no locale information form VFS is used on system startup 3398 // this is just to protect against null pointer exceptions 3399 i18nInfo = new CmsI18nInfo(Locale.ENGLISH, getSystemInfo().getDefaultEncoding()); 3400 } 3401 3402 // decode the requested resource, always using UTF-8 3403 requestedResource = CmsEncoder.decode(requestedResource); 3404 3405 // in case the current site could be configured for single tree localization, if so, remove the locale prefix if present 3406 CmsSite site = OpenCms.getSiteManager().getSiteForSiteRoot(siteRoot); 3407 if ((site != null) && CmsSite.LocalizationMode.singleTree.equals(site.getLocalizationMode())) { 3408 Locale locale = CmsSingleTreeLocaleHandler.getLocaleFromPath(requestedResource); 3409 if (locale != null) { 3410 requestedResource = requestedResource.substring( 3411 requestedResource.indexOf(locale.toString()) + locale.toString().length()); 3412 } 3413 } 3414 3415 // initialize the context info 3416 CmsContextInfo contextInfo = new CmsContextInfo( 3417 user, 3418 project, 3419 requestedResource, 3420 requestMatcher, 3421 siteRoot, 3422 isSecureRequest, 3423 i18nInfo.getLocale(), 3424 i18nInfo.getEncoding(), 3425 remoteAddr, 3426 requestTime, 3427 ouFqn, 3428 false); 3429 3430 // now generate and return the CmsObject 3431 return initCmsObject(contextInfo); 3432 } 3433 3434 /** 3435 * Handles the user authentification for each request sent to OpenCms.<p> 3436 * 3437 * User authentification is done in three steps: 3438 * <ol> 3439 * <li>Session authentification: OpenCms stores information of all authentificated 3440 * users in an internal storage based on the users session.</li> 3441 * <li>Authorization handler authentification: If the session authentification fails, 3442 * the current configured authorization handler is called.</li> 3443 * <li>Default user: When both authentification methods fail, the user is set to 3444 * the default (Guest) user.</li> 3445 * </ol> 3446 * 3447 * @param req the current http request 3448 * @param res the current http response 3449 * 3450 * @return the initialized cms context 3451 * 3452 * @throws IOException if user authentication fails 3453 * @throws CmsException in case something goes wrong 3454 */ 3455 private CmsObject initCmsObject(HttpServletRequest req, HttpServletResponse res) throws IOException, CmsException { 3456 3457 return initCmsObject(req, res, true); 3458 } 3459 3460 /** 3461 * Returns an initialized CmsObject with the given users permissions.<p> 3462 * 3463 * In case the password is <code>null</code>, or the user is the <code>Guest</code> user, 3464 * no password check is done. Therefore you can initialize all users without knowing their passwords 3465 * by just supplying <code>null</code> as password. This is intended only for 3466 * internal operation in the core.<p> 3467 * 3468 * @param req the current request 3469 * @param res the current response 3470 * @param user the user to initialize the CmsObject with 3471 * @param password the password of the user 3472 * @param ouFqn the organizational unit, if <code>null</code> the users ou is used 3473 * 3474 * @return a cms context that has been initialized with "Guest" permissions 3475 * 3476 * @throws CmsException in case the CmsObject could not be initialized 3477 */ 3478 private CmsObject initCmsObject( 3479 HttpServletRequest req, 3480 HttpServletResponse res, 3481 String user, 3482 String password, 3483 String ouFqn) 3484 throws CmsException { 3485 3486 String siteroot = null; 3487 // gather information from request if provided 3488 if (req != null) { 3489 siteroot = OpenCms.getSiteManager().matchRequest(req).getSiteRoot(); 3490 } 3491 // initialize the user 3492 if (user == null) { 3493 user = getDefaultUsers().getUserGuest(); 3494 } 3495 if (siteroot == null) { 3496 siteroot = "/"; 3497 } 3498 CmsObject cms = initCmsObject( 3499 req, 3500 m_securityManager.readUser(null, user), 3501 siteroot, 3502 CmsProject.ONLINE_PROJECT_ID, 3503 ouFqn); 3504 // login the user if different from Guest and password was provided 3505 if ((password != null) && !getDefaultUsers().isUserGuest(user)) { 3506 cms.loginUser(user, password, CmsContextInfo.LOCALHOST); 3507 } 3508 return cms; 3509 } 3510 3511 /** 3512 * Checks whether the given request targets the workplace UI servlet.<p> 3513 * 3514 * @param req the request 3515 * 3516 * @return <code>true</code> in case the given request targets the workplace UI servlet 3517 */ 3518 private boolean isWorkplaceServletRequest(HttpServletRequest req) { 3519 3520 String servletPath = req.getServletPath(); 3521 return (servletPath != null) && servletPath.startsWith(CmsSystemInfo.WORKPLACE_PATH); 3522 } 3523 3524 /** 3525 * Sets the init level of this OpenCmsCore object instance.<p> 3526 * 3527 * For a detailed description about the possible run levels, 3528 * please see {@link OpenCms#getRunLevel()}.<p> 3529 * 3530 * @param level the level to set 3531 */ 3532 private void setRunLevel(int level) { 3533 3534 if (m_instance != null) { 3535 if (m_instance.m_runLevel >= OpenCms.RUNLEVEL_1_CORE_OBJECT) { 3536 // otherwise the log is not available 3537 if (CmsLog.INIT.isInfoEnabled()) { 3538 CmsLog.INIT.info( 3539 Messages.get().getBundle().key( 3540 Messages.INIT_RUNLEVEL_CHANGE_2, 3541 Integer.valueOf(m_instance.m_runLevel), 3542 Integer.valueOf(level))); 3543 } 3544 } 3545 m_instance.m_runLevel = level; 3546 } 3547 } 3548 3549}