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.monitor; 029 030import org.opencms.cache.CmsLruCache; 031import org.opencms.cache.CmsMemoryObjectCache; 032import org.opencms.cache.CmsVfsMemoryObjectCache; 033import org.opencms.configuration.CmsSystemConfiguration; 034import org.opencms.db.CmsCacheSettings; 035import org.opencms.db.CmsDriverManager; 036import org.opencms.db.CmsDriverManager.ResourceOUCacheKey; 037import org.opencms.db.CmsDriverManager.ResourceOUMap; 038import org.opencms.db.CmsPublishedResource; 039import org.opencms.db.CmsSecurityManager; 040import org.opencms.file.CmsFile; 041import org.opencms.file.CmsGroup; 042import org.opencms.file.CmsObject; 043import org.opencms.file.CmsProject; 044import org.opencms.file.CmsProperty; 045import org.opencms.file.CmsPropertyDefinition; 046import org.opencms.file.CmsResource; 047import org.opencms.file.CmsUser; 048import org.opencms.flex.CmsFlexCache.CmsFlexCacheVariation; 049import org.opencms.i18n.CmsLocaleManager; 050import org.opencms.lock.CmsLock; 051import org.opencms.lock.CmsLockManager; 052import org.opencms.mail.CmsMailTransport; 053import org.opencms.mail.CmsSimpleMail; 054import org.opencms.main.CmsEvent; 055import org.opencms.main.CmsLog; 056import org.opencms.main.CmsSessionManager; 057import org.opencms.main.I_CmsEventListener; 058import org.opencms.main.OpenCms; 059import org.opencms.publish.CmsPublishHistory; 060import org.opencms.publish.CmsPublishJobInfoBean; 061import org.opencms.publish.CmsPublishQueue; 062import org.opencms.scheduler.I_CmsScheduledJob; 063import org.opencms.security.CmsAccessControlList; 064import org.opencms.security.CmsOrganizationalUnit; 065import org.opencms.security.CmsPermissionSet; 066import org.opencms.security.CmsRole; 067import org.opencms.security.I_CmsPermissionHandler; 068import org.opencms.util.CmsDateUtil; 069import org.opencms.util.CmsStringUtil; 070import org.opencms.util.CmsUUID; 071import org.opencms.util.PrintfFormat; 072import org.opencms.xml.CmsXmlContentDefinition; 073import org.opencms.xml.CmsXmlEntityResolver; 074 075import java.util.ArrayList; 076import java.util.Collections; 077import java.util.ConcurrentModificationException; 078import java.util.Date; 079import java.util.HashMap; 080import java.util.Iterator; 081import java.util.List; 082import java.util.Locale; 083import java.util.Map; 084import java.util.concurrent.ConcurrentHashMap; 085import java.util.concurrent.TimeUnit; 086 087import org.apache.commons.collections.Buffer; 088import org.apache.commons.collections.buffer.SynchronizedBuffer; 089import org.apache.commons.collections.map.LRUMap; 090import org.apache.commons.logging.Log; 091 092import com.google.common.cache.CacheBuilder; 093import com.google.common.cache.CacheLoader; 094import com.google.common.cache.LoadingCache; 095 096import jakarta.mail.internet.InternetAddress; 097 098/** 099 * Monitors OpenCms memory consumption.<p> 100 * 101 * The memory monitor also provides all kind of caches used in the OpenCms core.<p> 102 * 103 * @since 6.0.0 104 */ 105public class CmsMemoryMonitor implements I_CmsScheduledJob { 106 107 /** Cache types. */ 108 public enum CacheType { 109 /** Access Control Lists cache. */ 110 ACL, 111 /** Content Definition cache. */ 112 CONTENT_DEFINITION, 113 /** Group cache. */ 114 GROUP, 115 /** Has Role cache. */ 116 HAS_ROLE, 117 /** Locale cache. */ 118 LOCALE, 119 /** Lock cache. */ 120 LOCK, 121 /** Memory Object cache. */ 122 MEMORY_OBJECT, 123 /** Organizational Unit cache. */ 124 ORG_UNIT, 125 /** Organizational unit resources. */ 126 ORG_UNIT_RESOURCES, 127 /** Permission cache. */ 128 PERMISSION, 129 /** Offline Project cache. */ 130 PROJECT, 131 /** Project resources cache. */ 132 PROJECT_RESOURCES, 133 /** Property cache. */ 134 PROPERTY, 135 /** Property List cache. */ 136 PROPERTY_LIST, 137 /** Publish history cache. */ 138 PUBLISH_HISTORY, 139 /** Publish queue cache. */ 140 PUBLISH_QUEUE, 141 /** Published resources cache. */ 142 PUBLISHED_RESOURCES, 143 /** Resource cache. */ 144 RESOURCE, 145 /** Resource List cache. */ 146 RESOURCE_LIST, 147 /** Role List cache. */ 148 ROLE_LIST, 149 /** User cache. */ 150 USER, 151 /** User list cache. */ 152 USER_LIST, 153 /** User Groups cache. */ 154 USERGROUPS, 155 /** VFS Object cache. */ 156 VFS_OBJECT, 157 /** XML Entity Permanent cache. */ 158 XML_ENTITY_PERM, 159 /** XML Entity Temporary cache. */ 160 XML_ENTITY_TEMP; 161 } 162 163 /** The concurrency level for the guava caches. */ 164 static final int CONCURRENCY_LEVEL = 8; 165 166 /** Set interval for clearing the caches to 10 minutes. */ 167 private static final int INTERVAL_CLEAR = 1000 * 60 * 10; 168 169 /** The log object for this class. */ 170 private static final Log LOG = CmsLog.getLog(CmsMemoryMonitor.class); 171 172 /** Flag indicating if monitor is currently running. */ 173 private static boolean m_currentlyRunning; 174 175 /** Maximum depth for object size recursion. */ 176 private static final int MAX_DEPTH = 5; 177 178 /** Cache for access control lists. */ 179 private Map<String, CmsAccessControlList> m_cacheAccessControlList; 180 181 /** A temporary cache for XML content definitions. */ 182 private Map<String, CmsXmlContentDefinition> m_cacheContentDefinitions; 183 184 /** Cache for groups. */ 185 private Map<String, CmsGroup> m_cacheGroup; 186 187 /** Cache for roles. */ 188 private Map<String, Boolean> m_cacheHasRoles; 189 190 /** A cache for accelerated locale lookup. */ 191 private Map<String, Locale> m_cacheLocale; 192 193 /** Cache for the resource locks. */ 194 private Map<String, CmsLock> m_cacheLock; 195 196 /** The memory object cache map. */ 197 private Map<String, Object> m_cacheMemObject; 198 199 /** Cache for organizational units. */ 200 private Map<String, CmsOrganizationalUnit> m_cacheOrgUnit; 201 202 /** Cache for permission checks. */ 203 private Map<String, I_CmsPermissionHandler.CmsPermissionCheckResult> m_cachePermission; 204 205 /** Cache for offline projects. */ 206 private Map<String, CmsProject> m_cacheProject; 207 208 /** Cache for project resources. */ 209 private Map<String, List<CmsResource>> m_cacheProjectResources; 210 211 /** Cache for properties. */ 212 private Map<String, CmsProperty> m_cacheProperty; 213 214 /** Cache for property lists. */ 215 private Map<String, List<CmsProperty>> m_cachePropertyList; 216 217 /** Cache for published resources. */ 218 private Map<String, List<CmsPublishedResource>> m_cachePublishedResources; 219 220 /** Cache for resources. */ 221 private Map<String, CmsResource> m_cacheResource; 222 223 /** Cache for resource lists. */ 224 private Map<String, List<CmsResource>> m_cacheResourceList; 225 226 /** Cache for role lists. */ 227 private Map<String, List<CmsRole>> m_cacheRoleLists; 228 229 /** Cache for resource paths assigned to OUs. */ 230 private Map<String, List<String>> m_orgUnitResources; 231 232 /** Cache for user data. */ 233 private Map<String, CmsUser> m_cacheUser; 234 235 /** Cache for user groups. */ 236 private CmsGroupListCache m_cacheUserGroups; 237 238 /** Cache for user lists. */ 239 private Map<String, List<CmsUser>> m_cacheUserList; 240 241 /** The vfs memory cache map. */ 242 private Map<String, Object> m_cacheVfsObject; 243 244 /** A permanent cache to avoid multiple readings of often used files from the VFS. */ 245 private Map<String, byte[]> m_cacheXmlPermanentEntity; 246 247 /** A temporary cache to avoid multiple readings of often used files from the VFS. */ 248 private Map<String, byte[]> m_cacheXmlTemporaryEntity; 249 250 /** The memory monitor configuration. */ 251 private CmsMemoryMonitorConfiguration m_configuration; 252 253 /** Map to keep track of disabled caches. */ 254 private Map<CacheType, Boolean> m_disabled = new HashMap<CacheType, Boolean>(); 255 256 /** Interval in which emails are send. */ 257 private int m_intervalEmail; 258 259 /** Interval in which the log is written. */ 260 private int m_intervalLog; 261 262 /** Interval between 2 warnings. */ 263 private int m_intervalWarning; 264 265 /** The time the caches were last cleared. */ 266 private long m_lastClearCache; 267 268 /** The time the last status email was send. */ 269 private long m_lastEmailStatus; 270 271 /** The time the last warning email was send. */ 272 private long m_lastEmailWarning; 273 274 /** The time the last status log was written. */ 275 private long m_lastLogStatus; 276 277 /** The time the last warning log was written. */ 278 private long m_lastLogWarning; 279 280 /** The number of times the log entry was written. */ 281 private int m_logCount; 282 283 /** Memory percentage to reach to go to warning level. */ 284 private int m_maxUsagePercent; 285 286 /** The average memory status. */ 287 private CmsMemoryStatus m_memoryAverage; 288 289 /** The current memory status. */ 290 private CmsMemoryStatus m_memoryCurrent; 291 292 /** Contains the object to be monitored. */ 293 private Map<String, Object> m_monitoredObjects; 294 295 /** Buffer for publish history. */ 296 private Buffer m_publishHistory; 297 298 /** Buffer for publish jobs. */ 299 private Buffer m_publishQueue; 300 301 /** Cache for resource OU data. */ 302 private LoadingCache<ResourceOUCacheKey, ResourceOUMap> m_resourceOuCache; 303 304 /** Flag for memory warning mail send. */ 305 private boolean m_warningLoggedSinceLastStatus; 306 307 /** Flag for memory warning mail send. */ 308 private boolean m_warningSendSinceLastStatus; 309 310 /** 311 * Empty constructor, required by OpenCms scheduler.<p> 312 */ 313 public CmsMemoryMonitor() { 314 315 m_monitoredObjects = new HashMap<String, Object>(); 316 LoadingCache<ResourceOUCacheKey, ResourceOUMap> resourceOUCache = CacheBuilder.newBuilder().expireAfterWrite( 317 60, 318 TimeUnit.SECONDS).build(new CacheLoader<ResourceOUCacheKey, ResourceOUMap>() { 319 320 @Override 321 public ResourceOUMap load(ResourceOUCacheKey key) throws Exception { 322 323 ResourceOUMap result = new CmsDriverManager.ResourceOUMap(); 324 result.init(key.getDriverManager(), key.getDbContext()); 325 return result; 326 } 327 }); 328 m_resourceOuCache = resourceOUCache; 329 } 330 331 /** 332 * Creates a thread safe LRU cache map based on the guava cache builder.<p> 333 * Use this instead of synchronized maps for better performance.<p> 334 * 335 * @param capacity the cache capacity 336 * 337 * @return the cache map 338 */ 339 @SuppressWarnings("unchecked") 340 public static <T, V> Map<T, V> createLRUCacheMap(int capacity) { 341 342 CacheBuilder<?, ?> builder = CacheBuilder.newBuilder().concurrencyLevel(CONCURRENCY_LEVEL); 343 if (capacity >= 0) { 344 builder = builder.maximumSize(capacity); 345 } 346 return (Map<T, V>)(builder.build().asMap()); 347 } 348 349 /** 350 * Returns the size of objects that are instances of 351 * <code>byte[]</code>, <code>String</code>, <code>CmsFile</code>,<code>I_CmsLruCacheObject</code>.<p> 352 * For other objects, a size of 0 is returned. 353 * 354 * @param obj the object 355 * @return the size of the object 356 */ 357 public static int getMemorySize(Object obj) { 358 359 if (obj instanceof I_CmsMemoryMonitorable) { 360 return ((I_CmsMemoryMonitorable)obj).getMemorySize(); 361 } 362 363 if (obj instanceof byte[]) { 364 // will always be a total of 16 + 8 365 return 8 + (int)(Math.ceil(((byte[])obj).length / 16.0) * 16.0); 366 } 367 368 if (obj instanceof String) { 369 // will always be a total of 16 + 24 370 return 24 + (int)(Math.ceil(((String)obj).length() / 8.0) * 16.0); 371 } 372 373 if (obj instanceof CmsFile) { 374 CmsFile f = (CmsFile)obj; 375 if (f.getContents() != null) { 376 return f.getContents().length + 1024; 377 } else { 378 return 1024; 379 } 380 } 381 382 if (obj instanceof CmsUUID) { 383 return 184; // worst case if UUID String has been generated 384 } 385 386 if (obj instanceof CmsPermissionSet) { 387 return 16; // two ints 388 } 389 390 if (obj instanceof CmsResource) { 391 return 1024; // estimated size 392 } 393 394 if (obj instanceof CmsPublishedResource) { 395 return 512; // estimated size 396 } 397 398 if (obj instanceof CmsUser) { 399 return 2048; // estimated size 400 } 401 402 if (obj instanceof CmsGroup) { 403 return 512; // estimated size 404 } 405 406 if (obj instanceof CmsProject) { 407 return 512; // estimated size 408 } 409 410 if (obj instanceof Boolean) { 411 return 8; // one boolean 412 } 413 414 if (obj instanceof CmsProperty) { 415 int size = 8; 416 417 CmsProperty property = (CmsProperty)obj; 418 size += getMemorySize(property.getName()); 419 420 if (property.getResourceValue() != null) { 421 size += getMemorySize(property.getResourceValue()); 422 } 423 424 if (property.getStructureValue() != null) { 425 size += getMemorySize(property.getStructureValue()); 426 } 427 428 if (property.getOrigin() != null) { 429 size += getMemorySize(property.getOrigin()); 430 } 431 432 return size; 433 } 434 435 if (obj instanceof CmsPropertyDefinition) { 436 int size = 8; 437 438 CmsPropertyDefinition propDef = (CmsPropertyDefinition)obj; 439 size += getMemorySize(propDef.getName()); 440 size += getMemorySize(propDef.getId()); 441 442 return size; 443 } 444 445 return 8; 446 } 447 448 /** 449 * Returns the total value size of a list object.<p> 450 * 451 * @param listValue the list object 452 * @param depth the max recursion depth for calculation the size 453 * 454 * @return the size of the list object 455 */ 456 public static long getValueSize(List<?> listValue, int depth) { 457 458 long totalSize = 0; 459 try { 460 Object[] values = listValue.toArray(); 461 for (int i = 0, s = values.length; i < s; i++) { 462 463 Object obj = values[i]; 464 465 if (obj instanceof CmsAccessControlList) { 466 obj = ((CmsAccessControlList)obj).getPermissionMap(); 467 } 468 469 if (obj instanceof CmsFlexCacheVariation) { 470 obj = ((CmsFlexCacheVariation)obj).m_map; 471 } 472 473 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 474 totalSize += getValueSize((Map<?, ?>)obj, depth + 1); 475 continue; 476 } 477 478 if ((obj instanceof List) && (depth < MAX_DEPTH)) { 479 totalSize += getValueSize((List<?>)obj, depth + 1); 480 continue; 481 } 482 483 totalSize += getMemorySize(obj); 484 } 485 } catch (ConcurrentModificationException e) { 486 // this might happen since even the .toArray() method internally creates an iterator 487 } catch (Throwable t) { 488 // catch all other exceptions otherwise the whole monitor will stop working 489 if (LOG.isDebugEnabled()) { 490 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 491 } 492 } 493 494 return totalSize; 495 } 496 497 /** 498 * Returns the total value size of a map object.<p> 499 * 500 * @param mapValue the map object 501 * @param depth the max recursion depth for calculation the size 502 * 503 * @return the size of the map object 504 */ 505 public static long getValueSize(Map<?, ?> mapValue, int depth) { 506 507 long totalSize = 0; 508 try { 509 Object[] values = mapValue.values().toArray(); 510 for (int i = 0, s = values.length; i < s; i++) { 511 512 Object obj = values[i]; 513 514 if (obj instanceof CmsAccessControlList) { 515 obj = ((CmsAccessControlList)obj).getPermissionMap(); 516 } 517 518 if (obj instanceof CmsFlexCacheVariation) { 519 obj = ((CmsFlexCacheVariation)obj).m_map; 520 } 521 522 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 523 totalSize += getValueSize((Map<?, ?>)obj, depth + 1); 524 continue; 525 } 526 527 if ((obj instanceof List) && (depth < MAX_DEPTH)) { 528 totalSize += getValueSize((List<?>)obj, depth + 1); 529 continue; 530 } 531 532 totalSize += getMemorySize(obj); 533 } 534 } catch (ConcurrentModificationException e) { 535 // this might happen since even the .toArray() method internally creates an iterator 536 } catch (Throwable t) { 537 // catch all other exceptions otherwise the whole monitor will stop working 538 if (LOG.isDebugEnabled()) { 539 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 540 } 541 } 542 543 return totalSize; 544 } 545 546 /** 547 * Returns the value sizes of value objects within the monitored object.<p> 548 * 549 * @param obj the object 550 * 551 * @return the value sizes of value objects or "-"-fields 552 */ 553 public static long getValueSize(Object obj) { 554 555 if (obj instanceof CmsLruCache) { 556 return ((CmsLruCache)obj).size(); 557 } 558 559 if (obj instanceof Map) { 560 return getValueSize((Map<?, ?>)obj, 1); 561 } 562 563 if (obj instanceof List) { 564 return getValueSize((List<?>)obj, 1); 565 } 566 567 try { 568 return getMemorySize(obj); 569 } catch (Exception exc) { 570 return 0; 571 } 572 } 573 574 /** 575 * Caches the given acl under the given cache key.<p> 576 * 577 * @param key the cache key 578 * @param acl the acl to cache 579 */ 580 public void cacheACL(String key, CmsAccessControlList acl) { 581 582 if (m_disabled.get(CacheType.ACL) != null) { 583 return; 584 } 585 m_cacheAccessControlList.put(key, acl); 586 } 587 588 /** 589 * Caches the given content definition under the given cache key.<p> 590 * 591 * @param key the cache key 592 * @param contentDefinition the content definition to cache 593 */ 594 public void cacheContentDefinition(String key, CmsXmlContentDefinition contentDefinition) { 595 596 if (m_disabled.get(CacheType.CONTENT_DEFINITION) != null) { 597 return; 598 } 599 m_cacheContentDefinitions.put(key, contentDefinition); 600 } 601 602 /** 603 * Caches the given group under its id AND fully qualified name.<p> 604 * 605 * @param group the group to cache 606 */ 607 public void cacheGroup(CmsGroup group) { 608 609 if (m_disabled.get(CacheType.GROUP) != null) { 610 return; 611 } 612 m_cacheGroup.put(group.getId().toString(), group); 613 m_cacheGroup.put(group.getName(), group); 614 } 615 616 /** 617 * Caches the given locale under the given cache key.<p> 618 * 619 * @param key the cache key 620 * @param locale the locale to cache 621 */ 622 public void cacheLocale(String key, Locale locale) { 623 624 if (m_cacheLocale != null) { 625 if (m_disabled.get(CacheType.LOCALE) != null) { 626 return; 627 } 628 // this may be accessed before initialization 629 m_cacheLocale.put(key, locale); 630 } 631 } 632 633 /** 634 * Caches the given lock.<p> 635 * 636 * The lock is cached by it resource's root path.<p> 637 * 638 * @param lock the lock to cache 639 */ 640 public void cacheLock(CmsLock lock) { 641 642 if (m_disabled.get(CacheType.LOCK) != null) { 643 return; 644 } 645 m_cacheLock.put(lock.getResourceName(), lock); 646 } 647 648 /** 649 * Caches the given object under the given cache key.<p> 650 * 651 * @param key the cache key 652 * @param obj the object to cache 653 */ 654 public void cacheMemObject(String key, Object obj) { 655 656 if (m_disabled.get(CacheType.MEMORY_OBJECT) != null) { 657 return; 658 } 659 m_cacheMemObject.put(key, obj); 660 } 661 662 /** 663 * Caches the given organizational under its id AND the fully qualified name.<p> 664 * 665 * @param orgUnit the organizational unit to cache 666 */ 667 public void cacheOrgUnit(CmsOrganizationalUnit orgUnit) { 668 669 if (m_disabled.get(CacheType.ORG_UNIT) != null) { 670 return; 671 } 672 m_cacheOrgUnit.put(orgUnit.getId().toString(), orgUnit); 673 m_cacheOrgUnit.put(orgUnit.getName(), orgUnit); 674 } 675 676 /** 677 * Caches paths of resources assigned to an organizational unit. 678 * 679 * @param ou the OU FQN 680 * @param resources the list of associated resource paths 681 */ 682 public void cacheOrgUnitResources(String ou, List<String> resources) { 683 684 m_orgUnitResources.put(ou, Collections.unmodifiableList(new ArrayList<>(resources))); 685 } 686 687 /** 688 * Caches the given permission check result under the given cache key.<p> 689 * 690 * @param key the cache key 691 * @param permission the permission check result to cache 692 */ 693 public void cachePermission(String key, I_CmsPermissionHandler.CmsPermissionCheckResult permission) { 694 695 if (m_disabled.get(CacheType.PERMISSION) != null) { 696 return; 697 } 698 m_cachePermission.put(key, permission); 699 } 700 701 /** 702 * Caches the given project under its id AND the fully qualified name.<p> 703 * 704 * @param project the project to cache 705 */ 706 public void cacheProject(CmsProject project) { 707 708 if (m_disabled.get(CacheType.PROJECT) != null) { 709 return; 710 } 711 m_cacheProject.put(project.getUuid().toString(), project); 712 m_cacheProject.put(project.getName(), project); 713 } 714 715 /** 716 * Caches the given project resource list under the given cache key.<p> 717 * 718 * @param key the cache key 719 * @param projectResources the project resources to cache 720 */ 721 public void cacheProjectResources(String key, List<CmsResource> projectResources) { 722 723 if (m_disabled.get(CacheType.PROJECT_RESOURCES) != null) { 724 return; 725 } 726 m_cacheProjectResources.put(key, projectResources); 727 } 728 729 /** 730 * Caches the given property under the given cache key.<p> 731 * 732 * @param key the cache key 733 * @param property the property to cache 734 */ 735 public void cacheProperty(String key, CmsProperty property) { 736 737 if (m_disabled.get(CacheType.PROPERTY) != null) { 738 return; 739 } 740 m_cacheProperty.put(key, property); 741 } 742 743 /** 744 * Caches the given property list under the given cache key.<p> 745 * 746 * @param key the cache key 747 * @param propertyList the property list to cache 748 */ 749 public void cachePropertyList(String key, List<CmsProperty> propertyList) { 750 751 if (m_disabled.get(CacheType.PROPERTY_LIST) != null) { 752 return; 753 } 754 m_cachePropertyList.put(key, propertyList); 755 } 756 757 /** 758 * Caches the given published resources list under the given cache key.<p> 759 * 760 * @param cacheKey the cache key 761 * @param publishedResources the published resources list to cache 762 */ 763 public void cachePublishedResources(String cacheKey, List<CmsPublishedResource> publishedResources) { 764 765 if (m_disabled.get(CacheType.PUBLISHED_RESOURCES) != null) { 766 return; 767 } 768 if (publishedResources == null) { 769 m_cachePublishedResources.remove(cacheKey); 770 } else { 771 m_cachePublishedResources.put(cacheKey, publishedResources); 772 } 773 } 774 775 /** 776 * Caches the given publish job.<p> 777 * 778 * @param publishJob the publish job 779 */ 780 @SuppressWarnings("unchecked") 781 public void cachePublishJob(CmsPublishJobInfoBean publishJob) { 782 783 if (m_disabled.get(CacheType.PUBLISH_QUEUE) != null) { 784 return; 785 } 786 m_publishQueue.add(publishJob); 787 } 788 789 /** 790 * Caches the given publish job in the publish job history.<p> 791 * 792 * @param publishJob the publish job 793 */ 794 @SuppressWarnings("unchecked") 795 public void cachePublishJobInHistory(CmsPublishJobInfoBean publishJob) { 796 797 if (m_disabled.get(CacheType.PUBLISH_HISTORY) != null) { 798 return; 799 } 800 m_publishHistory.add(publishJob); 801 } 802 803 /** 804 * Caches the given resource under the given cache key.<p> 805 * 806 * @param key the cache key 807 * @param resource the resource to cache 808 */ 809 public void cacheResource(String key, CmsResource resource) { 810 811 if (m_disabled.get(CacheType.RESOURCE) != null) { 812 return; 813 } 814 m_cacheResource.put(key, resource); 815 } 816 817 /** 818 * Caches the given resource list under the given cache key.<p> 819 * 820 * @param key the cache key 821 * @param resourceList the resource list to cache 822 */ 823 public void cacheResourceList(String key, List<CmsResource> resourceList) { 824 825 if (m_disabled.get(CacheType.RESOURCE_LIST) != null) { 826 return; 827 } 828 if ((resourceList instanceof CmsDriverManager.ResourceListWithCacheability) 829 && !((CmsDriverManager.ResourceListWithCacheability)resourceList).isCacheable()) { 830 return; 831 } 832 m_cacheResourceList.put(key, resourceList); 833 } 834 835 /** 836 * Caches the given value under the given cache key.<p> 837 * 838 * @param key the cache key 839 * @param hasRole if the user has the given role 840 */ 841 public void cacheRole(String key, boolean hasRole) { 842 843 if (m_disabled.get(CacheType.HAS_ROLE) != null) { 844 return; 845 } 846 m_cacheHasRoles.put(key, Boolean.valueOf(hasRole)); 847 } 848 849 /** 850 * Caches the given value under the given cache key.<p> 851 * 852 * @param key the cache key 853 * @param roles the roles of the user 854 */ 855 public void cacheRoleList(String key, List<CmsRole> roles) { 856 857 if (m_disabled.get(CacheType.ROLE_LIST) != null) { 858 return; 859 } 860 m_cacheRoleLists.put(key, roles); 861 } 862 863 /** 864 * Caches the given user under its id AND the fully qualified name.<p> 865 * 866 * @param user the user to cache 867 */ 868 public void cacheUser(CmsUser user) { 869 870 if (m_disabled.get(CacheType.USER) != null) { 871 return; 872 } 873 m_cacheUser.put(user.getId().toString(), user); 874 m_cacheUser.put(user.getName(), user); 875 } 876 877 /** 878 * Caches the given list of users under the given cache key.<p> 879 * 880 * @param key the cache key 881 * @param userList the list of users to cache 882 */ 883 public void cacheUserList(String key, List<CmsUser> userList) { 884 885 if (m_disabled.get(CacheType.USER_LIST) != null) { 886 return; 887 } 888 m_cacheUserList.put(key, userList); 889 } 890 891 /** 892 * Caches the given vfs object under the given cache key.<p> 893 * 894 * @param key the cache key 895 * @param obj the vfs object to cache 896 */ 897 public void cacheVfsObject(String key, Object obj) { 898 899 if (m_disabled.get(CacheType.VFS_OBJECT) != null) { 900 return; 901 } 902 m_cacheVfsObject.put(key, obj); 903 } 904 905 /** 906 * Caches the given xml entity under the given system id.<p> 907 * 908 * @param systemId the cache key 909 * @param content the content to cache 910 */ 911 public void cacheXmlPermanentEntity(String systemId, byte[] content) { 912 913 if (m_disabled.get(CacheType.XML_ENTITY_PERM) != null) { 914 return; 915 } 916 m_cacheXmlPermanentEntity.put(systemId, content); 917 } 918 919 /** 920 * Caches the given xml entity under the given cache key.<p> 921 * 922 * @param key the cache key 923 * @param content the content to cache 924 */ 925 public void cacheXmlTemporaryEntity(String key, byte[] content) { 926 927 if (m_disabled.get(CacheType.XML_ENTITY_TEMP) != null) { 928 return; 929 } 930 m_cacheXmlTemporaryEntity.put(key, content); 931 } 932 933 /** 934 * Clears the access control list cache when access control entries are changed.<p> 935 */ 936 public void clearAccessControlListCache() { 937 938 flushCache(CacheType.ACL); 939 flushCache(CacheType.PERMISSION); 940 clearResourceCache(); 941 } 942 943 /** 944 * Clears almost all internal caches.<p> 945 */ 946 public void clearCache() { 947 948 clearPrincipalsCache(); 949 950 flushCache(CacheType.PROJECT); 951 flushCache(CacheType.RESOURCE); 952 flushCache(CacheType.RESOURCE_LIST); 953 flushCache(CacheType.PROPERTY); 954 flushCache(CacheType.PROPERTY_LIST); 955 flushCache(CacheType.PROJECT_RESOURCES); 956 flushCache(CacheType.PUBLISHED_RESOURCES); 957 flushCache(CacheType.ORG_UNIT_RESOURCES); 958 } 959 960 /** 961 * Clears the caches for publishing. 962 */ 963 public void clearCacheForPublishing() { 964 965 flushCache(CacheType.USER); 966 flushCache(CacheType.GROUP); 967 flushCache(CacheType.ORG_UNIT); 968 flushCache(CacheType.ACL); 969 flushCache(CacheType.PERMISSION); 970 flushCache(CacheType.HAS_ROLE); 971 flushCache(CacheType.ROLE_LIST); 972 flushCache(CacheType.USER_LIST); 973 flushCache(CacheType.PROJECT); 974 flushCache(CacheType.RESOURCE); 975 flushCache(CacheType.RESOURCE_LIST); 976 flushCache(CacheType.PROPERTY); 977 flushCache(CacheType.PROPERTY_LIST); 978 flushCache(CacheType.PROJECT_RESOURCES); 979 flushCache(CacheType.PUBLISHED_RESOURCES); 980 981 } 982 983 /** 984 * Clears all internal principal-related caches.<p> 985 */ 986 public void clearPrincipalsCache() { 987 988 flushCache(CacheType.USER); 989 flushCache(CacheType.GROUP); 990 flushCache(CacheType.ORG_UNIT); 991 flushCache(CacheType.ACL); 992 flushCache(CacheType.PERMISSION); 993 flushCache(CacheType.HAS_ROLE); 994 flushCache(CacheType.ROLE_LIST); 995 flushCache(CacheType.USERGROUPS); 996 flushCache(CacheType.USER_LIST); 997 } 998 999 /** 1000 * Clears all the depending caches when a resource was changed.<p> 1001 */ 1002 public void clearResourceCache() { 1003 1004 flushCache(CacheType.RESOURCE); 1005 flushCache(CacheType.RESOURCE_LIST); 1006 flushCache(CacheType.HAS_ROLE); 1007 flushCache(CacheType.ROLE_LIST); 1008 } 1009 1010 /** 1011 * Clears the user cache for the given user.<p> 1012 * 1013 * @param user the user 1014 */ 1015 public void clearUserCache(CmsUser user) { 1016 1017 uncacheUser(user); 1018 flushCache(CacheType.RESOURCE_LIST); 1019 } 1020 1021 /** 1022 * Disables the given cache.<p> 1023 * 1024 * @param types the cache type to disable 1025 */ 1026 public void disableCache(CacheType... types) { 1027 1028 for (CacheType type : types) { 1029 m_disabled.put(type, Boolean.TRUE); 1030 } 1031 flushCache(types); 1032 } 1033 1034 /** 1035 * Enables the given cache.<p> 1036 * 1037 * @param types the cache type to disable 1038 */ 1039 public void enableCache(CacheType... types) { 1040 1041 for (CacheType type : types) { 1042 m_disabled.remove(type); 1043 } 1044 } 1045 1046 /** 1047 * Returns if monitoring is enabled.<p> 1048 * 1049 * @return true if monitoring is enabled 1050 */ 1051 public boolean enabled() { 1052 1053 return true; 1054 } 1055 1056 /** 1057 * Flushes the ACL cache.<p> 1058 * 1059 * @deprecated use {@link #flushCache(CacheType[])} instead 1060 */ 1061 @Deprecated 1062 public void flushACLs() { 1063 1064 flushCache(CacheType.ACL); 1065 } 1066 1067 /** 1068 * Flushes the given cache.<p> 1069 * 1070 * @param types the cache types to flush 1071 */ 1072 public void flushCache(CacheType... types) { 1073 1074 for (CacheType type : types) { 1075 switch (type) { 1076 case ACL: 1077 m_cacheAccessControlList.clear(); 1078 break; 1079 case CONTENT_DEFINITION: 1080 m_cacheContentDefinitions.clear(); 1081 break; 1082 case GROUP: 1083 m_cacheGroup.clear(); 1084 break; 1085 case HAS_ROLE: 1086 m_cacheHasRoles.clear(); 1087 break; 1088 case LOCALE: 1089 m_cacheLocale.clear(); 1090 break; 1091 case LOCK: 1092 m_cacheLock.clear(); 1093 break; 1094 case MEMORY_OBJECT: 1095 m_cacheMemObject.clear(); 1096 break; 1097 case ORG_UNIT: 1098 m_cacheOrgUnit.clear(); 1099 break; 1100 case ORG_UNIT_RESOURCES: 1101 m_orgUnitResources.clear(); 1102 break; 1103 case PERMISSION: 1104 m_cachePermission.clear(); 1105 break; 1106 case PROJECT: 1107 m_cacheProject.clear(); 1108 break; 1109 case PROJECT_RESOURCES: 1110 m_cacheProjectResources.clear(); 1111 break; 1112 case PROPERTY: 1113 m_cacheProperty.clear(); 1114 break; 1115 case PROPERTY_LIST: 1116 m_cachePropertyList.clear(); 1117 break; 1118 case PUBLISHED_RESOURCES: 1119 m_cachePublishedResources.clear(); 1120 break; 1121 case PUBLISH_HISTORY: 1122 m_publishHistory.clear(); 1123 break; 1124 case PUBLISH_QUEUE: 1125 m_publishQueue.clear(); 1126 break; 1127 case RESOURCE: 1128 m_cacheResource.clear(); 1129 break; 1130 case RESOURCE_LIST: 1131 m_cacheResourceList.clear(); 1132 break; 1133 case ROLE_LIST: 1134 m_cacheRoleLists.clear(); 1135 m_resourceOuCache.invalidateAll(); 1136 break; 1137 case USER: 1138 m_cacheUser.clear(); 1139 break; 1140 case USERGROUPS: 1141 m_cacheUserGroups.clear(); 1142 break; 1143 case USER_LIST: 1144 m_cacheUserList.clear(); 1145 break; 1146 case VFS_OBJECT: 1147 m_cacheVfsObject.clear(); 1148 break; 1149 case XML_ENTITY_PERM: 1150 m_cacheXmlPermanentEntity.clear(); 1151 break; 1152 case XML_ENTITY_TEMP: 1153 m_cacheXmlTemporaryEntity.clear(); 1154 break; 1155 default: 1156 // can't happen 1157 } 1158 } 1159 } 1160 1161 /** 1162 * Flushes the xml content definitions cache.<p> 1163 * 1164 * @deprecated use {@link #flushCache(CacheType[])} instead 1165 */ 1166 @Deprecated 1167 public void flushContentDefinitions() { 1168 1169 flushCache(CacheType.CONTENT_DEFINITION); 1170 } 1171 1172 /** 1173 * Flushes the group cache.<p> 1174 * 1175 * @deprecated use {@link #flushCache(CacheType[])} instead 1176 */ 1177 @Deprecated 1178 public void flushGroups() { 1179 1180 flushCache(CacheType.GROUP); 1181 } 1182 1183 /** 1184 * Flushes the locale cache.<p> 1185 * 1186 * @deprecated use {@link #flushCache(CacheType[])} instead 1187 */ 1188 @Deprecated 1189 public void flushLocales() { 1190 1191 flushCache(CacheType.LOCALE); 1192 } 1193 1194 /** 1195 * Flushes the locks cache.<p> 1196 * 1197 * @param newLocks if not <code>null</code> the lock cache is replaced by the given map 1198 */ 1199 public void flushLocks(Map<String, CmsLock> newLocks) { 1200 1201 if ((newLocks == null) || newLocks.isEmpty()) { 1202 flushCache(CacheType.LOCK); 1203 return; 1204 } 1205 // initialize new lock cache 1206 Map<String, CmsLock> newLockCache = new ConcurrentHashMap<String, CmsLock>(newLocks); 1207 // register it 1208 register(CmsLockManager.class.getName(), newLockCache); 1209 // save the old cache 1210 Map<String, CmsLock> oldCache = m_cacheLock; 1211 // replace the old by the new cache 1212 m_cacheLock = newLockCache; 1213 // clean up the old cache 1214 oldCache.clear(); 1215 } 1216 1217 /** 1218 * Flushes the memory object cache.<p> 1219 * 1220 * @deprecated use {@link #flushCache(CacheType[])} instead 1221 */ 1222 @Deprecated 1223 public void flushMemObjects() { 1224 1225 flushCache(CacheType.MEMORY_OBJECT); 1226 } 1227 1228 /** 1229 * Flushes the organizational unit cache.<p> 1230 * 1231 * @deprecated use {@link #flushCache(CacheType[])} instead 1232 */ 1233 @Deprecated 1234 public void flushOrgUnits() { 1235 1236 flushCache(CacheType.ORG_UNIT); 1237 } 1238 1239 /** 1240 * Flushes the permission check result cache.<p> 1241 * 1242 * @deprecated use {@link #flushCache(CacheType[])} instead 1243 */ 1244 @Deprecated 1245 public void flushPermissions() { 1246 1247 flushCache(CacheType.PERMISSION); 1248 } 1249 1250 /** 1251 * Flushes the project resources cache.<p> 1252 * 1253 * @deprecated use {@link #flushCache(CacheType[])} instead 1254 */ 1255 @Deprecated 1256 public void flushProjectResources() { 1257 1258 flushCache(CacheType.PROJECT_RESOURCES); 1259 } 1260 1261 /** 1262 * Flushes the project cache.<p> 1263 * 1264 * @deprecated use {@link #flushCache(CacheType[])} instead 1265 */ 1266 @Deprecated 1267 public void flushProjects() { 1268 1269 flushCache(CacheType.PROJECT); 1270 } 1271 1272 /** 1273 * Flushes the property cache.<p> 1274 * 1275 * @deprecated use {@link #flushCache(CacheType[])} instead 1276 */ 1277 @Deprecated 1278 public void flushProperties() { 1279 1280 flushCache(CacheType.PROPERTY); 1281 } 1282 1283 /** 1284 * Flushes the property list cache.<p> 1285 * 1286 * @deprecated use {@link #flushCache(CacheType[])} instead 1287 */ 1288 @Deprecated 1289 public void flushPropertyLists() { 1290 1291 flushCache(CacheType.PROPERTY_LIST); 1292 } 1293 1294 /** 1295 * Flushes the published resources cache.<p> 1296 * 1297 * @deprecated use {@link #flushCache(CacheType[])} instead 1298 */ 1299 @Deprecated 1300 public void flushPublishedResources() { 1301 1302 flushCache(CacheType.PUBLISHED_RESOURCES); 1303 } 1304 1305 /** 1306 * Flushes the publish history.<p> 1307 * 1308 * @deprecated use {@link #flushCache(CacheType[])} instead 1309 */ 1310 @Deprecated 1311 public void flushPublishJobHistory() { 1312 1313 flushCache(CacheType.PUBLISH_HISTORY); 1314 } 1315 1316 /** 1317 * Flushes the publish queue.<p> 1318 * 1319 * @deprecated use {@link #flushCache(CacheType[])} instead 1320 */ 1321 @Deprecated 1322 public void flushPublishJobs() { 1323 1324 flushCache(CacheType.PUBLISH_QUEUE); 1325 } 1326 1327 /** 1328 * Flushes the resource list cache.<p> 1329 * 1330 * @deprecated use {@link #flushCache(CacheType[])} instead 1331 */ 1332 @Deprecated 1333 public void flushResourceLists() { 1334 1335 flushCache(CacheType.RESOURCE_LIST); 1336 } 1337 1338 /** 1339 * Flushes the resource cache.<p> 1340 * 1341 * @deprecated use {@link #flushCache(CacheType[])} instead 1342 */ 1343 @Deprecated 1344 public void flushResources() { 1345 1346 flushCache(CacheType.RESOURCE); 1347 } 1348 1349 /** 1350 * Flushes the role lists cache.<p> 1351 * 1352 * @deprecated use {@link #flushCache(CacheType[])} instead 1353 */ 1354 @Deprecated 1355 public void flushRoleLists() { 1356 1357 flushCache(CacheType.ROLE_LIST); 1358 } 1359 1360 /** 1361 * Flushes the roles cache.<p> 1362 * 1363 * @deprecated use {@link #flushCache(CacheType[])} instead 1364 */ 1365 @Deprecated 1366 public void flushRoles() { 1367 1368 flushCache(CacheType.HAS_ROLE); 1369 } 1370 1371 /** 1372 * Flushes the user groups cache.<p> 1373 * 1374 * @deprecated use {@link #flushCache(CacheType[])} instead 1375 */ 1376 @Deprecated 1377 public void flushUserGroups() { 1378 1379 flushCache(CacheType.USERGROUPS); 1380 flushCache(CacheType.USER_LIST); 1381 } 1382 1383 /** 1384 * Flushes the user group cache for the user with the given id. 1385 * 1386 * @param id the user id 1387 */ 1388 public void flushUserGroups(CmsUUID id) { 1389 1390 m_cacheUserGroups.clearUser(id); 1391 } 1392 1393 /** 1394 * Flushes the users cache.<p> 1395 * 1396 * @deprecated use {@link #flushCache(CacheType[])} instead 1397 */ 1398 @Deprecated 1399 public void flushUsers() { 1400 1401 flushCache(CacheType.USER); 1402 } 1403 1404 /** 1405 * Flushes the vfs object cache.<p> 1406 * 1407 * @deprecated use {@link #flushCache(CacheType[])} instead 1408 */ 1409 @Deprecated 1410 public void flushVfsObjects() { 1411 1412 flushCache(CacheType.VFS_OBJECT); 1413 } 1414 1415 /** 1416 * Flushes the xml permanent entities cache.<p> 1417 * 1418 * @deprecated use {@link #flushCache(CacheType[])} instead 1419 */ 1420 @Deprecated 1421 public void flushXmlPermanentEntities() { 1422 1423 flushCache(CacheType.XML_ENTITY_PERM); 1424 } 1425 1426 /** 1427 * Flushes the xml temporary entities cache.<p> 1428 * 1429 * @deprecated use {@link #flushCache(CacheType[])} instead 1430 */ 1431 @Deprecated 1432 public void flushXmlTemporaryEntities() { 1433 1434 flushCache(CacheType.XML_ENTITY_TEMP); 1435 } 1436 1437 /** 1438 * Returns all cached lock root paths.<p> 1439 * 1440 * @return a list of {@link String} objects 1441 */ 1442 public List<String> getAllCachedLockPaths() { 1443 1444 return new ArrayList<String>(m_cacheLock.keySet()); 1445 } 1446 1447 /** 1448 * Returns all cached locks.<p> 1449 * 1450 * @return a list of {@link CmsLock} objects 1451 */ 1452 public List<CmsLock> getAllCachedLocks() { 1453 1454 return new ArrayList<CmsLock>(m_cacheLock.values()); 1455 } 1456 1457 /** 1458 * Returns all cached publish jobs in the queue as ordered list.<p> 1459 * 1460 * @return all cached publish jobs 1461 */ 1462 @SuppressWarnings("unchecked") 1463 public List<CmsPublishJobInfoBean> getAllCachedPublishJobs() { 1464 1465 return new ArrayList<CmsPublishJobInfoBean>(m_publishQueue); 1466 } 1467 1468 /** 1469 * Returns all cached publish jobs in the history as ordered list.<p> 1470 * 1471 * @return all cached publish jobs 1472 */ 1473 @SuppressWarnings("unchecked") 1474 public List<CmsPublishJobInfoBean> getAllCachedPublishJobsInHistory() { 1475 1476 return new ArrayList<CmsPublishJobInfoBean>(m_publishHistory); 1477 } 1478 1479 /** 1480 * Returns the ACL cached with the given cache key or <code>null</code> if not found.<p> 1481 * 1482 * @param key the cache key to look for 1483 * 1484 * @return the ACL cached with the given cache key 1485 */ 1486 public CmsAccessControlList getCachedACL(String key) { 1487 1488 return m_cacheAccessControlList.get(key); 1489 } 1490 1491 /** 1492 * Returns the xml content definition cached with the given cache key or <code>null</code> if not found.<p> 1493 * 1494 * @param key the cache key to look for 1495 * 1496 * @return the xml content definition cached with the given cache key 1497 */ 1498 public CmsXmlContentDefinition getCachedContentDefinition(String key) { 1499 1500 return m_cacheContentDefinitions.get(key); 1501 } 1502 1503 /** 1504 * Returns the group cached with the given cache key or <code>null</code> if not found.<p> 1505 * 1506 * @param key the cache key to look for, this may be the group's uuid or the fqn 1507 * 1508 * @return the group cached with the given cache key 1509 */ 1510 public CmsGroup getCachedGroup(String key) { 1511 1512 return m_cacheGroup.get(key); 1513 } 1514 1515 /** 1516 * Returns the locale cached with the given cache key or <code>null</code> if not found.<p> 1517 * 1518 * @param key the cache key to look for 1519 * 1520 * @return the locale cached with the given cache key 1521 */ 1522 public Locale getCachedLocale(String key) { 1523 1524 if (m_cacheLocale == null) { 1525 // this may be accessed before initialization 1526 return null; 1527 } 1528 return m_cacheLocale.get(key); 1529 } 1530 1531 /** 1532 * Returns the lock cached with the given root path or <code>null</code> if not found.<p> 1533 * 1534 * @param rootPath the root path to look for 1535 * 1536 * @return the lock cached with the given root path 1537 */ 1538 public CmsLock getCachedLock(String rootPath) { 1539 1540 return m_cacheLock.get(rootPath); 1541 } 1542 1543 /** 1544 * Returns the memory object cached with the given cache key or <code>null</code> if not found.<p> 1545 * 1546 * @param key the cache key to look for 1547 * 1548 * @return the memory object cached with the given cache key 1549 */ 1550 public Object getCachedMemObject(String key) { 1551 1552 return m_cacheMemObject.get(key); 1553 } 1554 1555 /** 1556 * Returns the organizational unit cached with the given cache key or <code>null</code> if not found.<p> 1557 * 1558 * @param key the cache key to look for, this may be the organizational unit's uuid or the fqn 1559 * 1560 * @return the organizational unit cached with the given cache key 1561 */ 1562 public CmsOrganizationalUnit getCachedOrgUnit(String key) { 1563 1564 return m_cacheOrgUnit.get(key); 1565 } 1566 1567 /** 1568 * Gets the cached OU resource paths. 1569 * 1570 * @param ou the FQN of an organizational unit 1571 * @return the list of paths of the associated resources 1572 */ 1573 public List<String> getCachedOrgUnitResources(String ou) { 1574 1575 return m_orgUnitResources.get(ou); 1576 } 1577 1578 /** 1579 * Returns the permission check result cached with the given cache key or <code>null</code> if not found.<p> 1580 * 1581 * @param key the cache key to look for 1582 * 1583 * @return the permission check result cached with the given cache key 1584 */ 1585 public I_CmsPermissionHandler.CmsPermissionCheckResult getCachedPermission(String key) { 1586 1587 return m_cachePermission.get(key); 1588 } 1589 1590 /** 1591 * Returns the project cached with the given cache key or <code>null</code> if not found.<p> 1592 * 1593 * @param key the cache key to look for, this may be the project's uuid or the fqn 1594 * 1595 * @return the project cached with the given cache key 1596 */ 1597 public CmsProject getCachedProject(String key) { 1598 1599 return m_cacheProject.get(key); 1600 } 1601 1602 /** 1603 * Returns the project resources list cached with the given cache key or <code>null</code> if not found.<p> 1604 * 1605 * @param key the cache key to look for 1606 * 1607 * @return the project resources list cached with the given cache key 1608 */ 1609 public List<CmsResource> getCachedProjectResources(String key) { 1610 1611 return m_cacheProjectResources.get(key); 1612 } 1613 1614 /** 1615 * Returns the property cached with the given cache key or <code>null</code> if not found.<p> 1616 * 1617 * @param key the cache key to look for 1618 * 1619 * @return the property cached with the given cache key 1620 */ 1621 public CmsProperty getCachedProperty(String key) { 1622 1623 return m_cacheProperty.get(key); 1624 } 1625 1626 /** 1627 * Returns the property list cached with the given cache key or <code>null</code> if not found.<p> 1628 * 1629 * @param key the cache key to look for 1630 * 1631 * @return the property list cached with the given cache key 1632 */ 1633 public List<CmsProperty> getCachedPropertyList(String key) { 1634 1635 return m_cachePropertyList.get(key); 1636 } 1637 1638 /** 1639 * Returns the published resources list cached with the given cache key or <code>null</code> if not found.<p> 1640 * 1641 * @param cacheKey the cache key to look for 1642 * 1643 * @return the published resources list cached with the given cache key 1644 */ 1645 public List<CmsPublishedResource> getCachedPublishedResources(String cacheKey) { 1646 1647 return m_cachePublishedResources.get(cacheKey); 1648 } 1649 1650 /** 1651 * Returns the publish job with the given cache key or <code>null</code> if not found.<p> 1652 * 1653 * @param key the cache key to look for 1654 * 1655 * @return the publish job with the given cache key 1656 */ 1657 public CmsPublishJobInfoBean getCachedPublishJob(String key) { 1658 1659 synchronized (m_publishQueue) { 1660 for (Object obj : m_publishQueue) { 1661 CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj; 1662 if (publishJob.getPublishHistoryId().toString().equals(key)) { 1663 return publishJob; 1664 } 1665 } 1666 } 1667 return null; 1668 } 1669 1670 /** 1671 * Returns the publish job from the history with the given cache key or <code>null</code> if not found.<p> 1672 * 1673 * @param key the cache key to look for 1674 * 1675 * @return the publish job with the given cache key 1676 */ 1677 public CmsPublishJobInfoBean getCachedPublishJobInHistory(String key) { 1678 1679 for (Object obj : m_publishHistory) { 1680 CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)obj; 1681 if (publishJob.getPublishHistoryId().toString().equals(key)) { 1682 return publishJob; 1683 } 1684 } 1685 1686 return null; 1687 } 1688 1689 /** 1690 * Returns the resource cached with the given cache key or <code>null</code> if not found.<p> 1691 * 1692 * @param key the cache key to look for 1693 * 1694 * @return the resource cached with the given cache key 1695 */ 1696 public CmsResource getCachedResource(String key) { 1697 1698 return m_cacheResource.get(key); 1699 } 1700 1701 /** 1702 * Returns the resource list cached with the given cache key or <code>null</code> if not found.<p> 1703 * 1704 * @param key the cache key to look for 1705 * 1706 * @return the resource list cached with the given cache key 1707 */ 1708 public List<CmsResource> getCachedResourceList(String key) { 1709 1710 return m_cacheResourceList.get(key); 1711 } 1712 1713 /** 1714 * Returns the value cached with the given cache key or <code>null</code> if not found.<p> 1715 * 1716 * @param key the cache key to look for 1717 * 1718 * @return if the user has the given role 1719 */ 1720 public Boolean getCachedRole(String key) { 1721 1722 return m_cacheHasRoles.get(key); 1723 } 1724 1725 /** 1726 * Returns the value cached with the given cache key or <code>null</code> if not found.<p> 1727 * 1728 * @param key the cache key to look for 1729 * 1730 * @return list of roles 1731 */ 1732 public List<CmsRole> getCachedRoleList(String key) { 1733 1734 return m_cacheRoleLists.get(key); 1735 } 1736 1737 /** 1738 * Returns the user cached with the given cache key or <code>null</code> if not found.<p> 1739 * 1740 * @param key the cache key to look for, this may be the user's uuid or the fqn 1741 * 1742 * @return the user cached with the given cache key 1743 */ 1744 public CmsUser getCachedUser(String key) { 1745 1746 return m_cacheUser.get(key); 1747 } 1748 1749 /** 1750 * Returns the user groups list cached with the given cache key or <code>null</code> if not found.<p> 1751 * 1752 * @param userId the user id 1753 * @param key the cache key to look for 1754 * 1755 * @return the user groups list cached with the given cache key 1756 */ 1757 public List<CmsGroup> getCachedUserGroups(CmsUUID userId, String key) { 1758 1759 return m_cacheUserGroups.getGroups(userId, key); 1760 } 1761 1762 /** 1763 * Returns the user list cached with the given cache key or <code>null</code> if not found.<p> 1764 * 1765 * @param key the cache key to look for 1766 * 1767 * @return the user groups list cached with the given cache key 1768 */ 1769 public List<CmsUser> getCachedUserList(String key) { 1770 1771 return m_cacheUserList.get(key); 1772 } 1773 1774 /** 1775 * Returns the vfs object cached with the given cache key or <code>null</code> if not found.<p> 1776 * 1777 * @param key the cache key to look for 1778 * 1779 * @return the vfs object cached with the given cache key 1780 */ 1781 public Object getCachedVfsObject(String key) { 1782 1783 return m_cacheVfsObject.get(key); 1784 } 1785 1786 /** 1787 * Returns the xml permanent entity content cached with the given systemId or <code>null</code> if not found.<p> 1788 * 1789 * @param systemId the cache key to look for 1790 * 1791 * @return the xml permanent entity content cached with the given cache key 1792 */ 1793 public byte[] getCachedXmlPermanentEntity(String systemId) { 1794 1795 return m_cacheXmlPermanentEntity.get(systemId); 1796 } 1797 1798 /** 1799 * Returns the xml temporary entity content cached with the given cache key or <code>null</code> if not found.<p> 1800 * 1801 * @param key the cache key to look for 1802 * 1803 * @return the xml temporary entity content cached with the given cache key 1804 */ 1805 public byte[] getCachedXmlTemporaryEntity(String key) { 1806 1807 return m_cacheXmlTemporaryEntity.get(key); 1808 } 1809 1810 /** 1811 * Returns the configuration.<p> 1812 * 1813 * @return the configuration 1814 */ 1815 public CmsMemoryMonitorConfiguration getConfiguration() { 1816 1817 return m_configuration; 1818 } 1819 1820 /** 1821 * Returns the next publish job from the publish job queue.<p> 1822 * 1823 * @return the next publish job 1824 */ 1825 public CmsPublishJobInfoBean getFirstCachedPublishJob() { 1826 1827 synchronized (m_publishQueue) { 1828 if (!m_publishQueue.isEmpty()) { 1829 return (CmsPublishJobInfoBean)m_publishQueue.get(); 1830 } else { 1831 return null; 1832 } 1833 } 1834 } 1835 1836 /** 1837 * Gets the group list cache. 1838 * 1839 * @return the group list cache 1840 */ 1841 public CmsGroupListCache getGroupListCache() { 1842 1843 return m_cacheUserGroups; 1844 } 1845 1846 /** 1847 * Returns the log count.<p> 1848 * 1849 * @return the log count 1850 */ 1851 public int getLogCount() { 1852 1853 return m_logCount; 1854 } 1855 1856 /** 1857 * Returns the current memory status.<p> 1858 * 1859 * @return the memory status 1860 */ 1861 public CmsMemoryStatus getMemoryStatus() { 1862 1863 m_memoryCurrent.update(); 1864 return m_memoryCurrent; 1865 } 1866 1867 /** 1868 * Gets the cache for OU / resource associations. 1869 * 1870 * @return the cache 1871 */ 1872 public LoadingCache<ResourceOUCacheKey, ResourceOUMap> getResourceOuCache() { 1873 1874 return m_resourceOuCache; 1875 } 1876 1877 /** 1878 * Initializes the monitor with the provided configuration.<p> 1879 * 1880 * @param configuration the configuration to use 1881 */ 1882 public void initialize(CmsSystemConfiguration configuration) { 1883 1884 CmsCacheSettings cacheSettings = configuration.getCacheSettings(); 1885 1886 m_memoryAverage = new CmsMemoryStatus(); 1887 m_memoryCurrent = new CmsMemoryStatus(); 1888 1889 m_warningSendSinceLastStatus = false; 1890 m_warningLoggedSinceLastStatus = false; 1891 m_lastEmailWarning = 0; 1892 m_lastEmailStatus = 0; 1893 m_lastLogStatus = 0; 1894 m_lastLogWarning = 0; 1895 m_lastClearCache = 0; 1896 m_configuration = configuration.getCmsMemoryMonitorConfiguration(); 1897 1898 m_intervalWarning = 720 * 60000; 1899 m_maxUsagePercent = 90; 1900 1901 m_intervalEmail = m_configuration.getEmailInterval() * 1000; 1902 m_intervalLog = m_configuration.getLogInterval() * 1000; 1903 1904 if (m_configuration.getWarningInterval() > 0) { 1905 m_intervalWarning = m_configuration.getWarningInterval(); 1906 } 1907 m_intervalWarning *= 1000; 1908 1909 if (m_configuration.getMaxUsagePercent() > 0) { 1910 m_maxUsagePercent = m_configuration.getMaxUsagePercent(); 1911 } 1912 1913 if (CmsLog.INIT.isInfoEnabled()) { 1914 CmsLog.INIT.info( 1915 Messages.get().getBundle().key(Messages.LOG_MM_INTERVAL_LOG_1, Integer.valueOf(m_intervalLog / 1000))); 1916 CmsLog.INIT.info( 1917 Messages.get().getBundle().key( 1918 Messages.LOG_MM_INTERVAL_EMAIL_1, 1919 Integer.valueOf(m_intervalEmail / 1000))); 1920 CmsLog.INIT.info( 1921 Messages.get().getBundle().key( 1922 Messages.LOG_MM_INTERVAL_WARNING_1, 1923 Integer.valueOf(m_intervalWarning / 1000))); 1924 CmsLog.INIT.info( 1925 Messages.get().getBundle().key( 1926 Messages.LOG_MM_INTERVAL_MAX_USAGE_1, 1927 Integer.valueOf(m_maxUsagePercent))); 1928 1929 if ((m_configuration.getEmailReceiver() == null) || (m_configuration.getEmailSender() == null)) { 1930 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_DISABLED_0)); 1931 } else { 1932 CmsLog.INIT.info( 1933 Messages.get().getBundle().key(Messages.LOG_MM_EMAIL_SENDER_1, m_configuration.getEmailSender())); 1934 Iterator<String> i = m_configuration.getEmailReceiver().iterator(); 1935 int n = 0; 1936 while (i.hasNext()) { 1937 CmsLog.INIT.info( 1938 Messages.get().getBundle().key( 1939 Messages.LOG_MM_EMAIL_RECEIVER_2, 1940 Integer.valueOf(n + 1), 1941 i.next())); 1942 n++; 1943 } 1944 } 1945 } 1946 1947 // create and register all system caches 1948 1949 // temporary xml entities cache 1950 m_cacheXmlTemporaryEntity = createLRUCacheMap(128); 1951 register(CmsXmlEntityResolver.class.getName() + ".xmlEntityTemporaryCache", m_cacheXmlTemporaryEntity); 1952 1953 // permanent xml entities cache 1954 m_cacheXmlPermanentEntity = new ConcurrentHashMap<String, byte[]>(32); 1955 register(CmsXmlEntityResolver.class.getName() + ".xmlEntityPermanentCache", m_cacheXmlPermanentEntity); 1956 1957 // xml content definitions cache 1958 m_cacheContentDefinitions = createLRUCacheMap(64); 1959 register(CmsXmlEntityResolver.class.getName() + ".contentDefinitionsCache", m_cacheContentDefinitions); 1960 1961 // lock cache 1962 m_cacheLock = new ConcurrentHashMap<String, CmsLock>(); 1963 register(CmsLockManager.class.getName(), m_cacheLock); 1964 1965 // locale cache 1966 m_cacheLocale = new ConcurrentHashMap<String, Locale>(); 1967 register(CmsLocaleManager.class.getName(), m_cacheLocale); 1968 1969 // permissions cache 1970 m_cachePermission = createLRUCacheMap(cacheSettings.getPermissionCacheSize()); 1971 register(CmsSecurityManager.class.getName(), m_cachePermission); 1972 1973 // user cache 1974 m_cacheUser = createLRUCacheMap(cacheSettings.getUserCacheSize()); 1975 register(CmsDriverManager.class.getName() + ".userCache", m_cacheUser); 1976 1977 // user list cache 1978 m_cacheUserList = createLRUCacheMap(cacheSettings.getUserCacheSize()); 1979 register(CmsDriverManager.class.getName() + ".userListCache", m_cacheUserList); 1980 1981 // group cache 1982 m_cacheGroup = createLRUCacheMap(cacheSettings.getGroupCacheSize()); 1983 register(CmsDriverManager.class.getName() + ".groupCache", m_cacheGroup); 1984 1985 // organizational unit cache 1986 m_cacheOrgUnit = createLRUCacheMap(cacheSettings.getOrgUnitCacheSize()); 1987 register(CmsDriverManager.class.getName() + ".orgUnitCache", m_cacheOrgUnit); 1988 1989 m_orgUnitResources = createLRUCacheMap(-1); 1990 register(CmsDriverManager.class.getName() + ".orgUnitResources", m_orgUnitResources); 1991 1992 // user groups list cache 1993 m_cacheUserGroups = new CmsGroupListCache(cacheSettings.getUserGroupsCacheSize()); 1994 register(CmsDriverManager.class.getName() + ".userGroupsCache", m_cacheUserGroups); 1995 1996 // project cache 1997 m_cacheProject = createLRUCacheMap(cacheSettings.getProjectCacheSize()); 1998 register(CmsDriverManager.class.getName() + ".projectCache", m_cacheProject); 1999 2000 // project resources cache cache 2001 m_cacheProjectResources = createLRUCacheMap(cacheSettings.getProjectResourcesCacheSize()); 2002 register(CmsDriverManager.class.getName() + ".projectResourcesCache", m_cacheProjectResources); 2003 2004 // publish history 2005 int size = configuration.getPublishManager().getPublishHistorySize(); 2006 Buffer buffer = CmsPublishHistory.getQueue(size); 2007 m_publishHistory = SynchronizedBuffer.decorate(buffer); 2008 register(CmsPublishHistory.class.getName() + ".publishHistory", buffer); 2009 2010 // publish queue 2011 buffer = CmsPublishQueue.getQueue(); 2012 m_publishQueue = SynchronizedBuffer.decorate(buffer); 2013 register(CmsPublishQueue.class.getName() + ".publishQueue", buffer); 2014 2015 // resource cache 2016 m_cacheResource = createLRUCacheMap(cacheSettings.getResourceCacheSize()); 2017 register(CmsDriverManager.class.getName() + ".resourceCache", m_cacheResource); 2018 2019 // roles cache 2020 m_cacheHasRoles = createLRUCacheMap(cacheSettings.getRolesCacheSize()); 2021 register(CmsDriverManager.class.getName() + ".rolesCache", m_cacheHasRoles); 2022 2023 // role lists cache 2024 m_cacheRoleLists = createLRUCacheMap(cacheSettings.getRolesCacheSize()); 2025 register(CmsDriverManager.class.getName() + ".roleListsCache", m_cacheRoleLists); 2026 2027 // resource list cache 2028 m_cacheResourceList = createLRUCacheMap(cacheSettings.getResourcelistCacheSize()); 2029 register(CmsDriverManager.class.getName() + ".resourceListCache", m_cacheResourceList); 2030 2031 // property cache 2032 m_cacheProperty = createLRUCacheMap(cacheSettings.getPropertyCacheSize()); 2033 register(CmsDriverManager.class.getName() + ".propertyCache", m_cacheProperty); 2034 2035 // property list cache 2036 m_cachePropertyList = createLRUCacheMap(cacheSettings.getPropertyListsCacheSize()); 2037 register(CmsDriverManager.class.getName() + ".propertyListCache", m_cachePropertyList); 2038 2039 // published resources list cache 2040 m_cachePublishedResources = createLRUCacheMap(5); 2041 register(CmsDriverManager.class.getName() + ".publishedResourcesCache", m_cachePublishedResources); 2042 2043 // acl cache 2044 m_cacheAccessControlList = createLRUCacheMap(cacheSettings.getAclCacheSize()); 2045 register(CmsDriverManager.class.getName() + ".accessControlListCache", m_cacheAccessControlList); 2046 2047 // vfs object cache 2048 m_cacheVfsObject = new ConcurrentHashMap<String, Object>(); 2049 register(CmsVfsMemoryObjectCache.class.getName(), m_cacheVfsObject); 2050 2051 // memory object cache 2052 m_cacheMemObject = new ConcurrentHashMap<String, Object>(); 2053 register(CmsMemoryObjectCache.class.getName(), m_cacheMemObject); 2054 2055 if (LOG.isDebugEnabled()) { 2056 // this will happen only once during system startup 2057 LOG.debug(Messages.get().getBundle().key(Messages.LOG_MM_CREATED_1, new Date(System.currentTimeMillis()))); 2058 } 2059 } 2060 2061 /** 2062 * Checks if the property cache is enabled.<p> 2063 * 2064 * @return <code>true</code> if the property cache is enabled 2065 * 2066 * @deprecated use {@link #isEnabled(CacheType)} instead 2067 */ 2068 @Deprecated 2069 public boolean isCacheProperty() { 2070 2071 return isEnabled(CacheType.PROPERTY); 2072 } 2073 2074 /** 2075 * Checks if the property list cache is enabled.<p> 2076 * 2077 * @return <code>true</code> if the property list cache is enabled 2078 * 2079 * @deprecated use {@link #isEnabled(CacheType)} instead 2080 */ 2081 @Deprecated 2082 public boolean isCachePropertyList() { 2083 2084 return isEnabled(CacheType.PROPERTY_LIST); 2085 } 2086 2087 /** 2088 * Checks if the resource cache is enabled.<p> 2089 * 2090 * @return <code>true</code> if the resource cache is enabled 2091 * 2092 * @deprecated use {@link #isEnabled(CacheType)} instead 2093 */ 2094 @Deprecated 2095 public boolean isCacheResource() { 2096 2097 return isEnabled(CacheType.RESOURCE); 2098 } 2099 2100 /** 2101 * Checks if the resource list cache is enabled.<p> 2102 * 2103 * @return <code>true</code> if the resource list cache is enabled 2104 * 2105 * @deprecated use {@link #isEnabled(CacheType)} instead 2106 */ 2107 @Deprecated 2108 public boolean isCacheResourceList() { 2109 2110 return isEnabled(CacheType.RESOURCE_LIST); 2111 } 2112 2113 /** 2114 * Checks if the given cache is enabled.<p> 2115 * 2116 * @param type the cache type to check 2117 * 2118 * @return <code>true</code> if the given cache is enabled 2119 */ 2120 public boolean isEnabled(CacheType type) { 2121 2122 return (m_disabled.get(type) == null); 2123 } 2124 2125 /** 2126 * Checks if there is a registered monitored object with the given key.<p> 2127 * 2128 * @param key the key to look for 2129 * 2130 * @return <code>true</code> if there is a registered monitored object with the given key 2131 */ 2132 public boolean isMonitoring(String key) { 2133 2134 return (m_monitoredObjects.get(key) != null); 2135 } 2136 2137 /** 2138 * @see org.opencms.scheduler.I_CmsScheduledJob#launch(CmsObject, Map) 2139 */ 2140 public String launch(CmsObject cms, Map<String, String> parameters) throws Exception { 2141 2142 CmsMemoryMonitor monitor = OpenCms.getMemoryMonitor(); 2143 2144 // make sure job is not launched twice 2145 if (m_currentlyRunning) { 2146 return null; 2147 } 2148 2149 try { 2150 m_currentlyRunning = true; 2151 2152 // update the memory status 2153 monitor.updateStatus(); 2154 2155 // check if the system is in a low memory condition 2156 if (monitor.lowMemory()) { 2157 // log warning 2158 monitor.monitorWriteLog(true); 2159 // send warning email 2160 monitor.monitorSendEmail(true); 2161 // clean up caches 2162 monitor.clearCaches(); 2163 } 2164 2165 // check if regular a log entry must be written 2166 if ((System.currentTimeMillis() - monitor.m_lastLogStatus) > monitor.m_intervalLog) { 2167 monitor.monitorWriteLog(false); 2168 } 2169 2170 // check if the memory status email must be send 2171 if ((System.currentTimeMillis() - monitor.m_lastEmailStatus) > monitor.m_intervalEmail) { 2172 monitor.monitorSendEmail(false); 2173 } 2174 } finally { 2175 // make sure state is reset even if an error occurs, 2176 // otherwise MM will not be executed after an error 2177 m_currentlyRunning = false; 2178 } 2179 2180 return null; 2181 } 2182 2183 /** 2184 * Returns true if the system runs low on memory.<p> 2185 * 2186 * @return true if the system runs low on memory 2187 */ 2188 public boolean lowMemory() { 2189 2190 return ((m_maxUsagePercent > 0) && (m_memoryCurrent.getUsage() > m_maxUsagePercent)); 2191 } 2192 2193 /** 2194 * Adds a new object to the monitor.<p> 2195 * 2196 * @param objectName name of the object 2197 * @param object the object for monitoring 2198 */ 2199 public void register(String objectName, Object object) { 2200 2201 if (enabled()) { 2202 m_monitoredObjects.put(objectName, object); 2203 } 2204 } 2205 2206 /** 2207 * Checks if some kind of persistence is required.<p> 2208 * 2209 * This could be overwritten in a distributed environment.<p> 2210 * 2211 * @return <code>true</code> if some kind of persistence is required 2212 */ 2213 public boolean requiresPersistency() { 2214 2215 return true; 2216 } 2217 2218 /** 2219 * Sets if the property cache is enabled.<p> 2220 * 2221 * @param cacheProperty if the property cache is enabled 2222 * 2223 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2224 */ 2225 @Deprecated 2226 public void setCacheProperty(boolean cacheProperty) { 2227 2228 if (cacheProperty) { 2229 enableCache(CacheType.PROPERTY); 2230 } else { 2231 disableCache(CacheType.PROPERTY); 2232 } 2233 } 2234 2235 /** 2236 * Sets if the property list cache is enabled.<p> 2237 * 2238 * @param cachePropertyList if the property list cache is enabled 2239 * 2240 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2241 */ 2242 @Deprecated 2243 public void setCachePropertyList(boolean cachePropertyList) { 2244 2245 if (cachePropertyList) { 2246 enableCache(CacheType.PROPERTY_LIST); 2247 } else { 2248 disableCache(CacheType.PROPERTY_LIST); 2249 } 2250 } 2251 2252 /** 2253 * Sets if the resource cache is enabled.<p> 2254 * 2255 * @param cacheResource if the resource cache is enabled 2256 * 2257 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2258 */ 2259 @Deprecated 2260 public void setCacheResource(boolean cacheResource) { 2261 2262 if (cacheResource) { 2263 enableCache(CacheType.RESOURCE); 2264 } else { 2265 disableCache(CacheType.RESOURCE); 2266 } 2267 } 2268 2269 /** 2270 * Sets if the resource list cache is enabled.<p> 2271 * 2272 * @param cacheResourceList if the resource list cache is enabled 2273 * 2274 * @deprecated use {@link #enableCache(CacheType[])} or {@link #disableCache(CacheType[])} instead 2275 */ 2276 @Deprecated 2277 public void setCacheResourceList(boolean cacheResourceList) { 2278 2279 if (cacheResourceList) { 2280 enableCache(CacheType.RESOURCE_LIST); 2281 } else { 2282 disableCache(CacheType.RESOURCE_LIST); 2283 } 2284 } 2285 2286 /** 2287 * Flushes all cached objects.<p> 2288 * 2289 * @throws Exception if something goes wrong 2290 */ 2291 public void shutdown() throws Exception { 2292 2293 for (CacheType type : CacheType.values()) { 2294 flushCache(type); 2295 } 2296 } 2297 2298 /** 2299 * Removes the given xml content definition from the cache.<p> 2300 * 2301 * @param key the cache key to remove from cache 2302 */ 2303 public void uncacheContentDefinition(String key) { 2304 2305 m_cacheContentDefinitions.remove(key); 2306 } 2307 2308 /** 2309 * Removes the given group from the cache.<p> 2310 * 2311 * The group is removed by name AND also by uuid.<p> 2312 * 2313 * @param group the group to remove from cache 2314 */ 2315 public void uncacheGroup(CmsGroup group) { 2316 2317 m_cacheGroup.remove(group.getId().toString()); 2318 m_cacheGroup.remove(group.getName()); 2319 } 2320 2321 /** 2322 * Removes the cached lock for the given root path from the cache.<p> 2323 * 2324 * @param rootPath the root path of the lock to remove from cache 2325 */ 2326 public void uncacheLock(String rootPath) { 2327 2328 m_cacheLock.remove(rootPath); 2329 } 2330 2331 /** 2332 * Removes the given organizational unit from the cache.<p> 2333 * 2334 * The organizational unit is removed by name AND also by uuid.<p> 2335 * 2336 * @param orgUnit the organizational unit to remove from cache 2337 */ 2338 public void uncacheOrgUnit(CmsOrganizationalUnit orgUnit) { 2339 2340 m_cacheOrgUnit.remove(orgUnit.getId().toString()); 2341 m_cacheOrgUnit.remove(orgUnit.getName()); 2342 } 2343 2344 /** 2345 * Removes the given project from the cache.<p> 2346 * 2347 * The project is removed by name AND also by uuid.<p> 2348 * 2349 * @param project the project to remove from cache 2350 */ 2351 public void uncacheProject(CmsProject project) { 2352 2353 m_cacheProject.remove(project.getUuid().toString()); 2354 m_cacheProject.remove(project.getName()); 2355 } 2356 2357 /** 2358 * Removes the given publish job from the cache.<p> 2359 * 2360 * @param publishJob the publish job to remove 2361 */ 2362 public void uncachePublishJob(CmsPublishJobInfoBean publishJob) { 2363 2364 m_publishQueue.remove(publishJob); 2365 } 2366 2367 /** 2368 * Removes the given publish job from the history.<p> 2369 * 2370 * @param publishJob the publish job to remove 2371 */ 2372 public void uncachePublishJobInHistory(CmsPublishJobInfoBean publishJob) { 2373 2374 m_publishHistory.remove(publishJob); 2375 } 2376 2377 /** 2378 * Removes the given user from the cache.<p> 2379 * 2380 * The user is removed by name AND also by uuid.<p> 2381 * 2382 * @param user the user to remove from cache 2383 */ 2384 public void uncacheUser(CmsUser user) { 2385 2386 m_cacheUser.remove(user.getId().toString()); 2387 m_cacheUser.remove(user.getName()); 2388 } 2389 2390 /** 2391 * Removes the given vfs object from the cache.<p> 2392 * 2393 * @param key the cache key to remove from cache 2394 */ 2395 public void uncacheVfsObject(String key) { 2396 2397 m_cacheVfsObject.remove(key); 2398 } 2399 2400 /** 2401 * Removes the given xml temporary entity from the cache.<p> 2402 * 2403 * @param key the cache key to remove from cache 2404 */ 2405 public void uncacheXmlTemporaryEntity(String key) { 2406 2407 m_cacheXmlTemporaryEntity.remove(key); 2408 } 2409 2410 /** 2411 * Clears the OpenCms caches.<p> 2412 */ 2413 protected void clearCaches() { 2414 2415 if ((m_lastClearCache + INTERVAL_CLEAR) > System.currentTimeMillis()) { 2416 // if the cache has already been cleared less then 15 minutes ago we skip this because 2417 // clearing the caches to often will hurt system performance and the 2418 // setup seems to be in trouble anyway 2419 return; 2420 } 2421 m_lastClearCache = System.currentTimeMillis(); 2422 if (LOG.isWarnEnabled()) { 2423 LOG.warn(Messages.get().getBundle().key(Messages.LOG_CLEAR_CACHE_MEM_CONS_0)); 2424 } 2425 OpenCms.fireCmsEvent( 2426 new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap())); 2427 System.gc(); 2428 } 2429 2430 /** 2431 * Returns the cache costs of a monitored object.<p> 2432 * 2433 * <code>obj</code> must be of type {@link CmsLruCache}.<p> 2434 * 2435 * @param obj the object 2436 * 2437 * @return the cache costs or "-" 2438 */ 2439 protected long getCosts(Object obj) { 2440 2441 long costs = 0; 2442 if (obj instanceof CmsLruCache) { 2443 costs = ((CmsLruCache)obj).getObjectCosts(); 2444 if (costs < 0) { 2445 costs = 0; 2446 } 2447 } 2448 2449 return costs; 2450 } 2451 2452 /** 2453 * Returns the number of items within a monitored object.<p> 2454 * 2455 * <code>obj</code> must be of type {@link CmsLruCache} or {@link Map}.<p> 2456 * 2457 * @param obj the object 2458 * 2459 * @return the number of items or "-" 2460 */ 2461 protected String getItems(Object obj) { 2462 2463 if (obj instanceof CmsLruCache) { 2464 return Integer.toString(((CmsLruCache)obj).size()); 2465 } 2466 if (obj instanceof Map) { 2467 return Integer.toString(((Map<?, ?>)obj).size()); 2468 } 2469 if (obj instanceof CmsGroupListCache) { 2470 return "" + ((CmsGroupListCache)obj).size(); 2471 } 2472 return "-"; 2473 } 2474 2475 /** 2476 * Returns the total size of key strings within a monitored map.<p> 2477 * 2478 * The keys must be of type {@link String}.<p> 2479 * 2480 * @param map the map 2481 * @param depth the max recursion depth for calculation the size 2482 * 2483 * @return total size of key strings 2484 */ 2485 protected long getKeySize(Map<?, ?> map, int depth) { 2486 2487 long keySize = 0; 2488 try { 2489 Object[] values = map.values().toArray(); 2490 for (int i = 0, s = values.length; i < s; i++) { 2491 2492 Object obj = values[i]; 2493 2494 if ((obj instanceof Map) && (depth < MAX_DEPTH)) { 2495 keySize += getKeySize((Map<?, ?>)obj, depth + 1); 2496 continue; 2497 } 2498 } 2499 values = null; 2500 2501 Object[] keys = map.keySet().toArray(); 2502 for (int i = 0, s = keys.length; i < s; i++) { 2503 2504 Object obj = keys[i]; 2505 2506 if (obj instanceof String) { 2507 String st = (String)obj; 2508 keySize += (st.length() * 2); 2509 } 2510 } 2511 } catch (ConcurrentModificationException e) { 2512 // this might happen since even the .toArray() method internally creates an iterator 2513 } catch (Throwable t) { 2514 // catch all other exceptions otherwise the whole monitor will stop working 2515 if (LOG.isDebugEnabled()) { 2516 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CAUGHT_THROWABLE_1, t.getMessage())); 2517 } 2518 } 2519 2520 return keySize; 2521 } 2522 2523 /** 2524 * Returns the total size of key strings within a monitored object.<p> 2525 * 2526 * <code>obj</code> must be of type {@link Map}, the keys must be of type {@link String}.<p> 2527 * 2528 * @param obj the object 2529 * 2530 * @return the total size of key strings 2531 */ 2532 protected long getKeySize(Object obj) { 2533 2534 if (obj instanceof Map) { 2535 return getKeySize((Map<?, ?>)obj, 1); 2536 } 2537 2538 return 0; 2539 } 2540 2541 /** 2542 * Returns the max costs for all items within a monitored object.<p> 2543 * 2544 * <code>obj</code> must be of type {@link CmsLruCache} or {@link LRUMap}.<p> 2545 * 2546 * @param obj the object 2547 * 2548 * @return max cost limit or "-" 2549 */ 2550 protected String getLimit(Object obj) { 2551 2552 if (obj instanceof CmsLruCache) { 2553 return Long.toString(((CmsLruCache)obj).getMaxCacheCosts()); 2554 } 2555 if (obj instanceof LRUMap) { 2556 return Integer.toString(((LRUMap)obj).maxSize()); 2557 } 2558 2559 return "-"; 2560 } 2561 2562 /** 2563 * Sends a warning or status email with OpenCms Memory information.<p> 2564 * 2565 * @param warning if true, send a memory warning email 2566 */ 2567 protected void monitorSendEmail(boolean warning) { 2568 2569 if ((m_configuration.getEmailSender() == null) || (m_configuration.getEmailReceiver() == null)) { 2570 // send no mails if not fully configured 2571 return; 2572 } else if (warning 2573 && (m_warningSendSinceLastStatus 2574 && !((m_intervalEmail <= 0) 2575 && (System.currentTimeMillis() < (m_lastEmailWarning + m_intervalWarning))))) { 2576 // send no warning email if no status email has been send since the last warning 2577 // if status is disabled, send no warn email if warn interval has not passed 2578 return; 2579 } else if ((!warning) && (m_intervalEmail <= 0)) { 2580 // if email iterval is <= 0 status email is disabled 2581 return; 2582 } 2583 String date = CmsDateUtil.getDateTimeShort(System.currentTimeMillis()); 2584 String subject; 2585 String content = ""; 2586 if (warning) { 2587 m_warningSendSinceLastStatus = true; 2588 m_lastEmailWarning = System.currentTimeMillis(); 2589 subject = "OpenCms Memory W A R N I N G [" 2590 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2591 + "/" 2592 + date 2593 + "]"; 2594 content += "W A R N I N G !\nOpenCms memory consumption on server " 2595 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2596 + " has reached a critical level !\n\n" 2597 + "The configured limit is " 2598 + m_maxUsagePercent 2599 + "%\n\n"; 2600 } else { 2601 m_warningSendSinceLastStatus = false; 2602 m_lastEmailStatus = System.currentTimeMillis(); 2603 subject = "OpenCms Memory Status [" 2604 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2605 + "/" 2606 + date 2607 + "]"; 2608 } 2609 2610 content += "Memory usage report of OpenCms server " 2611 + OpenCms.getSystemInfo().getServerName().toUpperCase() 2612 + " at " 2613 + date 2614 + "\n\n" 2615 + "Memory maximum heap size: " 2616 + m_memoryCurrent.getMaxMemory() 2617 + " mb\n" 2618 + "Memory current heap size: " 2619 + m_memoryCurrent.getTotalMemory() 2620 + " mb\n\n" 2621 + "Memory currently used : " 2622 + m_memoryCurrent.getUsedMemory() 2623 + " mb (" 2624 + m_memoryCurrent.getUsage() 2625 + "%)\n" 2626 + "Memory currently unused : " 2627 + m_memoryCurrent.getFreeMemory() 2628 + " mb\n\n\n"; 2629 2630 if (warning) { 2631 content += "*** Please take action NOW to ensure that no OutOfMemoryException occurs.\n\n\n"; 2632 } 2633 2634 CmsSessionManager sm = OpenCms.getSessionManager(); 2635 2636 if (sm != null) { 2637 content += "Current status of the sessions:\n\n"; 2638 content += "Logged in users : " + sm.getSessionCountAuthenticated() + "\n"; 2639 content += "Currently active sessions: " + sm.getSessionCountCurrent() + "\n"; 2640 content += "Total created sessions : " + sm.getSessionCountTotal() + "\n\n\n"; 2641 } 2642 2643 sm = null; 2644 2645 content += "Current status of the caches:\n\n"; 2646 List<String> keyList = new ArrayList<String>(m_monitoredObjects.keySet()); 2647 Collections.sort(keyList); 2648 long totalSize = 0; 2649 for (Iterator<String> keys = keyList.iterator(); keys.hasNext();) { 2650 String key = keys.next(); 2651 String[] shortKeys = key.split("\\."); 2652 String shortKey = shortKeys[shortKeys.length - 2] + '.' + shortKeys[shortKeys.length - 1]; 2653 PrintfFormat form = new PrintfFormat("%9s"); 2654 Object obj = m_monitoredObjects.get(key); 2655 2656 long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj); 2657 totalSize += size; 2658 2659 content += new PrintfFormat("%-42.42s").sprintf(shortKey) 2660 + " " 2661 + "Entries: " 2662 + form.sprintf(getItems(obj)) 2663 + " " 2664 + "Limit: " 2665 + form.sprintf(getLimit(obj)) 2666 + " " 2667 + "Size: " 2668 + form.sprintf(Long.toString(size)) 2669 + "\n"; 2670 } 2671 content += "\nTotal size of cache memory monitored: " + totalSize + " (" + (totalSize / 1048576) + ")\n\n"; 2672 2673 String from = m_configuration.getEmailSender(); 2674 List<InternetAddress> receivers = new ArrayList<InternetAddress>(); 2675 List<String> receiverEmails = m_configuration.getEmailReceiver(); 2676 try { 2677 if ((from != null) && (receiverEmails != null) && !receiverEmails.isEmpty()) { 2678 Iterator<String> i = receiverEmails.iterator(); 2679 while (i.hasNext()) { 2680 receivers.add(new InternetAddress(i.next())); 2681 } 2682 CmsSimpleMail email = new CmsSimpleMail(); 2683 email.setFrom(from); 2684 email.setTo(receivers); 2685 email.setSubject(subject); 2686 email.setMsg(content); 2687 new CmsMailTransport(email).send(); 2688 } 2689 if (LOG.isInfoEnabled()) { 2690 if (warning) { 2691 LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_WARNING_EMAIL_SENT_0)); 2692 } else { 2693 LOG.info(Messages.get().getBundle().key(Messages.LOG_MM_STATUS_EMAIL_SENT_0)); 2694 } 2695 } 2696 } catch (Exception e) { 2697 e.printStackTrace(); 2698 } 2699 } 2700 2701 /** 2702 * Write a warning or status log entry with OpenCms Memory information.<p> 2703 * 2704 * @param warning if true, write a memory warning log entry 2705 */ 2706 protected void monitorWriteLog(boolean warning) { 2707 2708 if (!LOG.isWarnEnabled()) { 2709 // we need at last warn level for this output 2710 return; 2711 } else if ((!warning) && (!LOG.isInfoEnabled())) { 2712 // if not warning we need info level 2713 return; 2714 } else if (warning 2715 && (m_warningLoggedSinceLastStatus 2716 && !(((m_intervalLog <= 0) 2717 && (System.currentTimeMillis() < (m_lastLogWarning + m_intervalWarning)))))) { 2718 // write no warning log if no status log has been written since the last warning 2719 // if status is disabled, log no warn entry if warn interval has not passed 2720 return; 2721 } else if ((!warning) && (m_intervalLog <= 0)) { 2722 // if log interval is <= 0 status log is disabled 2723 return; 2724 } 2725 2726 if (warning) { 2727 m_lastLogWarning = System.currentTimeMillis(); 2728 m_warningLoggedSinceLastStatus = true; 2729 LOG.warn( 2730 Messages.get().getBundle().key( 2731 Messages.LOG_MM_WARNING_MEM_CONSUME_2, 2732 Long.valueOf(m_memoryCurrent.getUsage()), 2733 Integer.valueOf(m_maxUsagePercent))); 2734 } else { 2735 m_warningLoggedSinceLastStatus = false; 2736 m_lastLogStatus = System.currentTimeMillis(); 2737 } 2738 2739 if (warning) { 2740 LOG.warn( 2741 Messages.get().getBundle().key( 2742 Messages.LOG_MM_WARNING_MEM_STATUS_6, 2743 new Object[] { 2744 Long.valueOf(m_memoryCurrent.getMaxMemory()), 2745 Long.valueOf(m_memoryCurrent.getTotalMemory()), 2746 Long.valueOf(m_memoryCurrent.getFreeMemory()), 2747 Long.valueOf(m_memoryCurrent.getUsedMemory()), 2748 Long.valueOf(m_memoryCurrent.getUsage()), 2749 Integer.valueOf(m_maxUsagePercent)})); 2750 } else { 2751 m_logCount++; 2752 LOG.info( 2753 Messages.get().getBundle().key( 2754 Messages.LOG_MM_LOG_INFO_2, 2755 OpenCms.getSystemInfo().getServerName().toUpperCase(), 2756 String.valueOf(m_logCount))); 2757 2758 List<String> keyList = new ArrayList<String>(m_monitoredObjects.keySet()); 2759 Collections.sort(keyList); 2760 long totalSize = 0; 2761 for (Iterator<String> keys = keyList.iterator(); keys.hasNext();) { 2762 String key = keys.next(); 2763 Object obj = m_monitoredObjects.get(key); 2764 2765 long size = getKeySize(obj) + getValueSize(obj) + getCosts(obj); 2766 totalSize += size; 2767 2768 PrintfFormat name1 = new PrintfFormat("%-80s"); 2769 PrintfFormat name2 = new PrintfFormat("%-50s"); 2770 PrintfFormat form = new PrintfFormat("%9s"); 2771 LOG.info( 2772 Messages.get().getBundle().key( 2773 Messages.LOG_MM_NOWARN_STATUS_5, 2774 new Object[] { 2775 name1.sprintf(key), 2776 name2.sprintf(obj.getClass().getName()), 2777 form.sprintf(getItems(obj)), 2778 form.sprintf(getLimit(obj)), 2779 form.sprintf(Long.toString(size))})); 2780 } 2781 2782 LOG.info( 2783 Messages.get().getBundle().key( 2784 Messages.LOG_MM_WARNING_MEM_STATUS_6, 2785 new Object[] { 2786 Long.valueOf(m_memoryCurrent.getMaxMemory()), 2787 Long.valueOf(m_memoryCurrent.getTotalMemory()), 2788 Long.valueOf(m_memoryCurrent.getFreeMemory()), 2789 Long.valueOf(m_memoryCurrent.getUsedMemory()), 2790 Long.valueOf(m_memoryCurrent.getUsage()), 2791 Integer.valueOf(m_maxUsagePercent), 2792 Long.valueOf(totalSize), 2793 Long.valueOf(totalSize / 1048576)}) 2794 2795 ); 2796 LOG.info( 2797 Messages.get().getBundle().key( 2798 Messages.LOG_MM_WARNING_MEM_STATUS_AVG_6, 2799 new Object[] { 2800 Long.valueOf(m_memoryAverage.getMaxMemory()), 2801 Long.valueOf(m_memoryAverage.getTotalMemory()), 2802 Long.valueOf(m_memoryAverage.getFreeMemory()), 2803 Long.valueOf(m_memoryAverage.getUsedMemory()), 2804 Long.valueOf(m_memoryAverage.getUsage()), 2805 Integer.valueOf(m_memoryAverage.getCount())})); 2806 2807 CmsSessionManager sm = OpenCms.getSessionManager(); 2808 2809 if (sm != null) { 2810 LOG.info( 2811 Messages.get().getBundle().key( 2812 Messages.LOG_MM_SESSION_STAT_3, 2813 String.valueOf(sm.getSessionCountAuthenticated()), 2814 String.valueOf(sm.getSessionCountCurrent()), 2815 String.valueOf(sm.getSessionCountTotal()))); 2816 } 2817 sm = null; 2818 2819 for (Iterator<String> i = OpenCms.getSqlManager().getDbPoolUrls().iterator(); i.hasNext();) { 2820 String poolname = i.next(); 2821 try { 2822 LOG.info( 2823 Messages.get().getBundle().key( 2824 Messages.LOG_MM_CONNECTIONS_3, 2825 poolname, 2826 Integer.toString(OpenCms.getSqlManager().getActiveConnections(poolname)), 2827 Integer.toString(OpenCms.getSqlManager().getIdleConnections(poolname)))); 2828 } catch (Exception exc) { 2829 LOG.info( 2830 Messages.get().getBundle().key( 2831 Messages.LOG_MM_CONNECTIONS_3, 2832 poolname, 2833 Integer.toString(-1), 2834 Integer.toString(-1))); 2835 } 2836 } 2837 2838 LOG.info( 2839 Messages.get().getBundle().key( 2840 Messages.LOG_MM_STARTUP_TIME_2, 2841 CmsDateUtil.getDateTimeShort(OpenCms.getSystemInfo().getStartupTime()), 2842 CmsStringUtil.formatRuntime(OpenCms.getSystemInfo().getRuntime()))); 2843 } 2844 } 2845 2846 /** 2847 * Updates the memory information of the memory monitor.<p> 2848 */ 2849 protected void updateStatus() { 2850 2851 m_memoryCurrent.update(); 2852 m_memoryAverage.calculateAverage(m_memoryCurrent); 2853 } 2854}