001package org.cache2k.ee.impl; 002 003/* 004 * #%L 005 * cache2k ee 006 * %% 007 * Copyright (C) 2000 - 2016 headissue GmbH, Munich 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import org.cache2k.Cache; 024import org.cache2k.CacheManager; 025import org.cache2k.core.CacheLifeCycleListener; 026import org.cache2k.core.CacheManagerImpl; 027import org.cache2k.core.CacheManagerLifeCycleListener; 028import org.cache2k.core.InternalCache; 029 030import javax.management.InstanceNotFoundException; 031import javax.management.MBeanServer; 032import javax.management.ObjectName; 033import java.lang.management.ManagementFactory; 034import java.util.Map; 035import java.util.WeakHashMap; 036 037/** 038 * Adds optional support for JMX. 039 */ 040public class JmxSupport implements CacheLifeCycleListener, CacheManagerLifeCycleListener { 041 042 int seenClassLoaderCount = 1; 043 Map<ClassLoader, Integer> classLoader2Integer = new WeakHashMap<ClassLoader, Integer>(); 044 045 @Override 046 public void cacheCreated(CacheManager cm, Cache c) { 047 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 048 if (c instanceof InternalCache) { 049 String _name = standardName(cm, c); 050 try { 051 mbs.registerMBean( 052 new CacheMXBeanImpl((InternalCache) c), 053 new ObjectName(_name)); 054 } catch (Exception e) { 055 throw new IllegalStateException("Error registering JMX bean, name='" + _name + "'", e); 056 } 057 } 058 } 059 060 @Override 061 public void cacheDestroyed(CacheManager cm, Cache c) { 062 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 063 if (c instanceof InternalCache) { 064 String _name = standardName(cm, c); 065 try { 066 mbs.unregisterMBean(new ObjectName(_name)); 067 } catch (InstanceNotFoundException ignore) { 068 } catch (Exception e) { 069 throw new IllegalStateException("Error deregistering JMX bean, name='" + _name + "'", e); 070 } 071 } 072 } 073 074 @Override 075 public void managerCreated(CacheManager m) { 076 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 077 String _name = cacheManagerNameWithClassLoader(m); 078 try { 079 mbs.registerMBean(new ManagerMXBeanImpl((CacheManagerImpl) m),new ObjectName(_name)); 080 } catch (Exception e) { 081 throw new IllegalStateException("Error register JMX bean, name='" + _name + "'", e); 082 } 083 } 084 085 @Override 086 public void managerDestroyed(CacheManager m) { 087 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 088 String _name = cacheManagerNameWithClassLoader(m); 089 try { 090 mbs.unregisterMBean(new ObjectName(_name)); 091 } catch (InstanceNotFoundException ignore) { 092 } catch (Exception e) { 093 throw new IllegalStateException("Error unregister JMX bean, name='" + _name + "'", e); 094 } 095 } 096 097 private static String cacheManagerName(CacheManager cm) { 098 return 099 "org.cache2k" + ":" + 100 "type=CacheManager" + 101 ",name=" + cm.getName(); 102 } 103 104 private static String cacheManagerNameWithClassLoaderNumber(CacheManager cm, int _classLoaderNumber) { 105 return 106 "org.cache2k" + ":" + 107 "type=CacheManager" + 108 ",name=" + cm.getName() + 109 ",uniqueClassLoaderNumber=" + _classLoaderNumber; 110 } 111 112 /** 113 * JSR107 allows cache managers with identical names within different class loaders. 114 * If multiple class loaders are involved, we need to add a qualifier to separate the names. 115 */ 116 private synchronized int getUniqueClassLoaderNumber(ClassLoader _classLoader) { 117 Integer no = classLoader2Integer.get(_classLoader); 118 if (no == null) { 119 no = seenClassLoaderCount++; 120 classLoader2Integer.put(_classLoader, no); 121 } 122 return no; 123 } 124 125 private synchronized String cacheManagerNameWithClassLoader(CacheManager cm) { 126 ClassLoader _classLoader = cm.getClassLoader(); 127 int no = getUniqueClassLoaderNumber(_classLoader); 128 if (no == 1) { 129 return cacheManagerName(cm); 130 } 131 return cacheManagerNameWithClassLoaderNumber(cm, no); 132 } 133 134 private synchronized String standardName(CacheManager cm, Cache c) { 135 int _classLoaderNumber = getUniqueClassLoaderNumber(cm.getClassLoader()); 136 if (_classLoaderNumber == 1) { 137 return 138 "org.cache2k" + ":" + 139 "type=Cache" + 140 ",manager=" + cm.getName() + 141 ",name=" + c.getName(); 142 } 143 return 144 "org.cache2k" + ":" + 145 "type=Cache" + 146 ",manager=" + cm.getName() + 147 ",uniqueClassLoaderNumber=" + _classLoaderNumber + 148 ",name=" + c.getName(); 149 150 } 151 152}