Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 1,091   Methods: 108
NCLOC: 811   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CacheJmxWrapper.java 70.8% 86.8% 88% 83.6%
coverage coverage
 1    /*
 2    * JBoss, Home of Professional Open Source.
 3    * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 4    * as indicated by the @author tags. See the copyright.txt file in the
 5    * distribution for a full listing of individual contributors.
 6    *
 7    * This is free software; you can redistribute it and/or modify it
 8    * under the terms of the GNU Lesser General Public License as
 9    * published by the Free Software Foundation; either version 2.1 of
 10    * the License, or (at your option) any later version.
 11    *
 12    * This software is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15    * Lesser General Public License for more details.
 16    *
 17    * You should have received a copy of the GNU Lesser General Public
 18    * License along with this software; if not, write to the Free
 19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 21    */
 22    package org.jboss.cache.jmx;
 23   
 24    import org.apache.commons.logging.Log;
 25    import org.apache.commons.logging.LogFactory;
 26    import org.jboss.cache.Cache;
 27    import org.jboss.cache.CacheException;
 28    import org.jboss.cache.CacheImpl;
 29    import org.jboss.cache.CacheStatus;
 30    import org.jboss.cache.DefaultCacheFactory;
 31    import org.jboss.cache.config.BuddyReplicationConfig;
 32    import org.jboss.cache.config.CacheLoaderConfig;
 33    import org.jboss.cache.config.Configuration;
 34    import org.jboss.cache.config.ConfigurationException;
 35    import org.jboss.cache.config.EvictionConfig;
 36    import org.jboss.cache.config.RuntimeConfig;
 37    import org.jboss.cache.factories.XmlConfigurationParser;
 38    import org.jboss.cache.interceptors.Interceptor;
 39    import org.jgroups.Address;
 40    import org.jgroups.Channel;
 41    import org.jgroups.ChannelFactory;
 42    import org.jgroups.jmx.JChannelFactoryMBean;
 43    import org.w3c.dom.Element;
 44   
 45    import javax.management.AttributeChangeNotification;
 46    import javax.management.JMException;
 47    import javax.management.ListenerNotFoundException;
 48    import javax.management.MBeanNotificationInfo;
 49    import javax.management.MBeanRegistration;
 50    import javax.management.MBeanServer;
 51    import javax.management.MalformedObjectNameException;
 52    import javax.management.NotificationBroadcasterSupport;
 53    import javax.management.NotificationFilter;
 54    import javax.management.NotificationListener;
 55    import javax.management.ObjectName;
 56    import javax.transaction.TransactionManager;
 57    import java.util.List;
 58    import java.util.concurrent.atomic.AtomicInteger;
 59    import java.util.concurrent.atomic.AtomicLong;
 60   
 61    /**
 62    * Wrapper class that exposes a
 63    * {@link CacheJmxWrapperMBean JMX management interface} for an instance of
 64    * {@link CacheImpl}.
 65    *
 66    * @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
 67    * @version $Revision: 1.29 $
 68    */
 69    public class CacheJmxWrapper
 70    extends NotificationBroadcasterSupport
 71    implements CacheJmxWrapperMBean, MBeanRegistration, CacheNotificationBroadcaster
 72    {
 73    private Log log = LogFactory.getLog(getClass().getName());
 74   
 75    private MBeanServer server;
 76    private String cacheObjectName;
 77    private boolean interceptorsRegistered;
 78    private CacheImpl<?, ?> cache;
 79    private Configuration config;
 80    private boolean registerInterceptors = true;
 81    private final AtomicInteger listenerCount = new AtomicInteger(0);
 82    private final AtomicLong sequence = new AtomicLong(0);
 83    private final CacheNotificationListener cacheNotificationListener;
 84    private CacheStatus cacheStatus;
 85    private String notificationServiceName;
 86    private boolean registered;
 87    private boolean disableStateChangeNotifications;
 88   
 89    // Legacy config support
 90   
 91    private Element buddyReplConfig;
 92    private Element evictionConfig;
 93    private Element cacheLoaderConfig;
 94    private Element clusterConfig;
 95    private JChannelFactoryMBean multiplexerService;
 96   
 97    // ----------------------------------------------------------- Constructors
 98   
 99  76 public CacheJmxWrapper()
 100    {
 101  76 cacheNotificationListener = new CacheNotificationListener(this);
 102  76 cacheStatus = CacheStatus.INSTANTIATED;
 103    }
 104   
 105  25 public CacheJmxWrapper(Cache cache)
 106    {
 107  25 this();
 108  25 setCache(cache);
 109    }
 110   
 111    // --------------------------------------------------- CacheJmxWrapperMBean
 112   
 113  8 public org.jboss.cache.Cache getCache()
 114    {
 115  8 return cache;
 116    }
 117   
 118  56 public Configuration getConfiguration()
 119    {
 120  56 Configuration cfg = (cache == null ? config : cache.getConfiguration());
 121  56 if (cfg == null)
 122    {
 123  3 cfg = config = new Configuration();
 124    }
 125  56 return cfg;
 126    }
 127   
 128  2 public String getConfigurationAsString()
 129    {
 130  2 Configuration cfg = getConfiguration();
 131  2 return cfg == null ? "Configuration is null" : cfg.toString();
 132    }
 133   
 134  2 public String getConfigurationAsHtmlString()
 135    {
 136  2 Configuration cfg = getConfiguration();
 137  2 return cfg == null ? "Configuration is null" : formatHtml(cfg.toString());
 138    }
 139   
 140  1 public String getCacheDetails()
 141    {
 142  1 return cache == null ? "Cache is null" : cache.printDetails();
 143    }
 144   
 145  1 public String getCacheDetailsAsHtml()
 146    {
 147  1 return cache == null ? "Cache is null" : formatHtml(cache.printDetails());
 148    }
 149   
 150  7 public CacheStatus getCacheStatus()
 151    {
 152  7 return cacheStatus;
 153    }
 154   
 155  249 public int getState()
 156    {
 157  249 switch (cacheStatus)
 158    {
 159  2 case INSTANTIATED:
 160  0 case CREATING:
 161  2 return registered ? REGISTERED : UNREGISTERED;
 162  42 case CREATED:
 163  42 return CREATED;
 164  42 case STARTING:
 165  42 return STARTING;
 166  79 case STARTED:
 167  79 return STARTED;
 168  40 case STOPPING:
 169  40 return STOPPING;
 170  39 case STOPPED:
 171  0 case DESTROYING:
 172  39 return STOPPED;
 173  2 case DESTROYED:
 174  2 return registered ? DESTROYED : UNREGISTERED;
 175  3 case FAILED:
 176  0 default:
 177  3 return FAILED;
 178    }
 179    }
 180   
 181  2 public Address getLocalAddress()
 182    {
 183  2 return cache == null ? null : cache.getLocalAddress();
 184    }
 185   
 186  1 public List<Address> getMembers()
 187    {
 188  1 return cache == null ? null : cache.getMembers();
 189    }
 190   
 191  3 public int getNumberOfNodes()
 192    {
 193  3 return cache == null ? -1 : cache.getNumberOfNodes();
 194    }
 195   
 196  3 public int getNumberOfAttributes()
 197    {
 198  3 return cache == null ? -1 : cache.getNumberOfAttributes();
 199    }
 200   
 201  3 public String getLockInfo()
 202    {
 203  3 return cache == null ? "Cache is null" : cache.printLockInfo();
 204    }
 205   
 206  1 public String getLockInfoAsHtml()
 207    {
 208  1 return cache == null ? "Cache is null" : formatHtml(cache.printLockInfo());
 209    }
 210   
 211  0 public boolean getRegisterInterceptors()
 212    {
 213  0 return registerInterceptors;
 214    }
 215   
 216  31 public void setRegisterInterceptors(boolean register)
 217    {
 218  31 this.registerInterceptors = register;
 219    }
 220   
 221    // ---------------------------------------------------- LegacyConfiguration
 222   
 223  1 public Element getBuddyReplicationConfig()
 224    {
 225  1 return buddyReplConfig;
 226    }
 227   
 228  1 public Element getCacheLoaderConfig()
 229    {
 230  1 return cacheLoaderConfig;
 231    }
 232   
 233  0 public Element getCacheLoaderConfiguration()
 234    {
 235  0 log.warn("MBean attribute 'CacheLoaderConfiguration' is deprecated; " +
 236    "use 'CacheLoaderConfig'");
 237  0 return getCacheLoaderConfig();
 238    }
 239   
 240  1 public String getCacheMode()
 241    {
 242  1 return getConfiguration().getCacheModeString();
 243    }
 244   
 245  1 public String getClusterName()
 246    {
 247  1 return getConfiguration().getClusterName();
 248    }
 249   
 250  0 public String getClusterProperties()
 251    {
 252  0 return getConfiguration().getClusterConfig();
 253    }
 254   
 255  1 public Element getClusterConfig()
 256    {
 257  1 return clusterConfig;
 258    }
 259   
 260  1 public Element getEvictionPolicyConfig()
 261    {
 262  1 return evictionConfig;
 263    }
 264   
 265  1 public boolean getExposeManagementStatistics()
 266    {
 267  1 return getConfiguration().getExposeManagementStatistics();
 268    }
 269   
 270  0 public boolean getUseInterceptorMbeans()
 271    {
 272  0 log.warn("MBean attribute 'UseInterceptorMbeans' is deprecated; " +
 273    "use 'ExposeManagementStatistics'");
 274  0 return getExposeManagementStatistics();
 275    }
 276   
 277  1 public boolean getFetchInMemoryState()
 278    {
 279  1 return getConfiguration().isFetchInMemoryState();
 280    }
 281   
 282  1 public long getStateRetrievalTimeout()
 283    {
 284  1 return getConfiguration().getStateRetrievalTimeout();
 285    }
 286   
 287  1 @Deprecated
 288    public void setInitialStateRetrievalTimeout(long timeout)
 289    {
 290  1 setStateRetrievalTimeout(timeout);
 291    }
 292   
 293  1 public String getIsolationLevel()
 294    {
 295  1 return getConfiguration().getIsolationLevelString();
 296    }
 297   
 298  1 public long getLockAcquisitionTimeout()
 299    {
 300  1 return getConfiguration().getLockAcquisitionTimeout();
 301    }
 302   
 303  0 public JChannelFactoryMBean getMultiplexerService()
 304    {
 305  0 return multiplexerService;
 306    }
 307   
 308  0 public String getMultiplexerStack()
 309    {
 310  0 return getConfiguration().getMultiplexerStack();
 311    }
 312   
 313  1 public ChannelFactory getMuxChannelFactory()
 314    {
 315  1 return getConfiguration().getRuntimeConfig().getMuxChannelFactory();
 316    }
 317   
 318  1 public String getNodeLockingScheme()
 319    {
 320  1 return getConfiguration().getNodeLockingSchemeString();
 321    }
 322   
 323  1 public long getReplQueueInterval()
 324    {
 325  1 return getConfiguration().getReplQueueInterval();
 326    }
 327   
 328  1 public int getReplQueueMaxElements()
 329    {
 330  1 return getConfiguration().getReplQueueMaxElements();
 331    }
 332   
 333  1 public String getReplicationVersion()
 334    {
 335  1 return getConfiguration().getReplVersionString();
 336    }
 337   
 338  1 public boolean getSyncCommitPhase()
 339    {
 340  1 return getConfiguration().isSyncCommitPhase();
 341    }
 342   
 343  1 public long getSyncReplTimeout()
 344    {
 345  1 return getConfiguration().getSyncReplTimeout();
 346    }
 347   
 348  1 public boolean getSyncRollbackPhase()
 349    {
 350  1 return getConfiguration().isSyncRollbackPhase();
 351    }
 352   
 353  1 public TransactionManager getTransactionManager()
 354    {
 355  1 return getConfiguration().getRuntimeConfig().getTransactionManager();
 356    }
 357   
 358  1 public String getTransactionManagerLookupClass()
 359    {
 360  1 return getConfiguration().getTransactionManagerLookupClass();
 361    }
 362   
 363  1 public boolean getUseRegionBasedMarshalling()
 364    {
 365  1 return getConfiguration().isUseRegionBasedMarshalling();
 366    }
 367   
 368  1 public boolean getUseReplQueue()
 369    {
 370  1 return getConfiguration().isUseReplQueue();
 371    }
 372   
 373  1 public boolean isInactiveOnStartup()
 374    {
 375  1 return getConfiguration().isInactiveOnStartup();
 376    }
 377   
 378  1 public void setBuddyReplicationConfig(Element config)
 379    {
 380  1 BuddyReplicationConfig brc = null;
 381  1 if (config != null)
 382    {
 383  1 brc = XmlConfigurationParser.parseBuddyReplicationConfig(config);
 384    }
 385  1 getConfiguration().setBuddyReplicationConfig(brc);
 386  1 this.buddyReplConfig = config;
 387    }
 388   
 389  1 public void setCacheLoaderConfig(Element cache_loader_config)
 390    {
 391  1 CacheLoaderConfig clc = null;
 392  1 if (cache_loader_config != null)
 393    {
 394  1 clc = XmlConfigurationParser.parseCacheLoaderConfig(cache_loader_config);
 395    }
 396  1 getConfiguration().setCacheLoaderConfig(clc);
 397  1 this.cacheLoaderConfig = cache_loader_config;
 398    }
 399   
 400  0 public void setCacheLoaderConfiguration(Element config)
 401    {
 402  0 log.warn("MBean attribute 'CacheLoaderConfiguration' is deprecated; " +
 403    "use 'CacheLoaderConfig'");
 404  0 setCacheLoaderConfig(config);
 405    }
 406   
 407  1 public void setCacheMode(String mode) throws Exception
 408    {
 409  1 getConfiguration().setCacheModeString(mode);
 410    }
 411   
 412  1 public void setClusterConfig(Element config)
 413    {
 414  1 String props = null;
 415  1 if (config != null)
 416    {
 417  1 props = XmlConfigurationParser.parseClusterConfigXml(config);
 418    }
 419  1 getConfiguration().setClusterConfig(props);
 420  1 this.clusterConfig = config;
 421    }
 422   
 423  1 @Deprecated
 424    public long getInitialStateRetrievalTimeout()
 425    {
 426  1 return getStateRetrievalTimeout();
 427    }
 428   
 429  1 public void setClusterName(String name)
 430    {
 431  1 getConfiguration().setClusterName(name);
 432    }
 433   
 434  0 public void setClusterProperties(String cluster_props)
 435    {
 436  0 getConfiguration().setClusterConfig(cluster_props);
 437    }
 438   
 439  1 public void setEvictionPolicyConfig(Element config)
 440    {
 441  1 EvictionConfig ec = null;
 442  1 if (config != null)
 443    {
 444  1 ec = XmlConfigurationParser.parseEvictionConfig(config);
 445    }
 446  1 getConfiguration().setEvictionConfig(ec);
 447  1 this.evictionConfig = config;
 448    }
 449   
 450  1 public void setExposeManagementStatistics(boolean expose)
 451    {
 452  1 getConfiguration().setExposeManagementStatistics(expose);
 453    }
 454   
 455  0 public void setUseInterceptorMbeans(boolean use)
 456    {
 457  0 log.warn("MBean attribute 'UseInterceptorMbeans' is deprecated; " +
 458    "use 'ExposeManagementStatistics'");
 459  0 setExposeManagementStatistics(use);
 460    }
 461   
 462  1 public void setFetchInMemoryState(boolean flag)
 463    {
 464  1 getConfiguration().setFetchInMemoryState(flag);
 465    }
 466   
 467  1 public void setInactiveOnStartup(boolean inactiveOnStartup)
 468    {
 469  1 getConfiguration().setInactiveOnStartup(inactiveOnStartup);
 470    }
 471   
 472  1 public void setStateRetrievalTimeout(long timeout)
 473    {
 474  1 getConfiguration().setStateRetrievalTimeout(timeout);
 475    }
 476   
 477  1 public void setIsolationLevel(String level)
 478    {
 479  1 getConfiguration().setIsolationLevelString(level);
 480    }
 481   
 482  1 public void setLockAcquisitionTimeout(long timeout)
 483    {
 484  1 getConfiguration().setLockAcquisitionTimeout(timeout);
 485    }
 486   
 487  1 public void setMultiplexerService(JChannelFactoryMBean muxService)
 488    {
 489  1 this.multiplexerService = muxService;
 490    }
 491   
 492  1 public void setMultiplexerStack(String stackName)
 493    {
 494  1 getConfiguration().setMultiplexerStack(stackName);
 495    }
 496   
 497  1 public void setMuxChannelFactory(ChannelFactory factory)
 498    {
 499  1 getConfiguration().getRuntimeConfig().setMuxChannelFactory(factory);
 500    }
 501   
 502  1 public void setNodeLockingScheme(String nodeLockingScheme)
 503    {
 504  1 getConfiguration().setNodeLockingSchemeString(nodeLockingScheme);
 505    }
 506   
 507  1 public void setReplQueueInterval(long interval)
 508    {
 509  1 getConfiguration().setReplQueueInterval(interval);
 510    }
 511   
 512  1 public void setReplQueueMaxElements(int max_elements)
 513    {
 514  1 getConfiguration().setReplQueueMaxElements(max_elements);
 515    }
 516   
 517  1 public void setReplicationVersion(String version)
 518    {
 519  1 getConfiguration().setReplVersionString(version);
 520    }
 521   
 522  1 public void setSyncCommitPhase(boolean sync_commit_phase)
 523    {
 524  1 getConfiguration().setSyncCommitPhase(sync_commit_phase);
 525    }
 526   
 527  1 public void setSyncReplTimeout(long timeout)
 528    {
 529  1 getConfiguration().setSyncReplTimeout(timeout);
 530    }
 531   
 532  1 public void setSyncRollbackPhase(boolean sync_rollback_phase)
 533    {
 534  1 getConfiguration().setSyncRollbackPhase(sync_rollback_phase);
 535    }
 536   
 537  1 public void setTransactionManager(TransactionManager manager)
 538    {
 539  1 getConfiguration().getRuntimeConfig().setTransactionManager(manager);
 540    }
 541   
 542  1 public void setTransactionManagerLookupClass(String cl) throws Exception
 543    {
 544  1 getConfiguration().setTransactionManagerLookupClass(cl);
 545    }
 546   
 547  1 public void setUseRegionBasedMarshalling(boolean isTrue)
 548    {
 549  1 getConfiguration().setUseRegionBasedMarshalling(isTrue);
 550    }
 551   
 552  1 public void setUseReplQueue(boolean flag)
 553    {
 554  1 getConfiguration().setUseReplQueue(flag);
 555    }
 556   
 557    // -------------------------------------------------------------- Lifecycle
 558   
 559  43 public void create() throws CacheException
 560    {
 561  43 if (cacheStatus.createAllowed() == false)
 562    {
 563  1 if (cacheStatus.needToDestroyFailedCache())
 564  0 destroy();
 565    else
 566  1 return;
 567    }
 568   
 569  42 try
 570    {
 571  42 cacheStatus = CacheStatus.CREATING;
 572   
 573  42 if (cache == null)
 574    {
 575  13 if (config == null)
 576    {
 577  0 throw new ConfigurationException("Must call setConfiguration() or setCache() before call to create()");
 578    }
 579   
 580  13 constructCache();
 581    }
 582   
 583  42 cache.create();
 584   
 585  42 cacheStatus = CacheStatus.CREATED;
 586    }
 587    catch (Throwable t)
 588    {
 589  0 handleLifecycleTransitionFailure(t);
 590    }
 591    }
 592   
 593  42 public void start() throws CacheException
 594    {
 595  42 if (cacheStatus.startAllowed() == false)
 596    {
 597  8 if (cacheStatus.needToDestroyFailedCache())
 598  1 destroy(); // this will take us back to DESTROYED
 599   
 600  8 if (cacheStatus.needCreateBeforeStart())
 601  7 create();
 602    else
 603  1 return;
 604    }
 605   
 606  41 try
 607    {
 608  41 int oldState = getState();
 609  41 cacheStatus = CacheStatus.STARTING;
 610  41 int startingState = getState();
 611  41 sendStateChangeNotification(oldState, startingState, getClass().getSimpleName() + " starting", null);
 612   
 613  41 cache.start();
 614   
 615  40 registerInterceptors();
 616   
 617  40 cacheStatus = CacheStatus.STARTED;
 618  40 sendStateChangeNotification(startingState, getState(), getClass().getSimpleName() + " started", null);
 619    }
 620    catch (Throwable t)
 621    {
 622  1 handleLifecycleTransitionFailure(t);
 623    }
 624    }
 625   
 626  54 public void stop()
 627    {
 628  54 if (cacheStatus.stopAllowed() == false)
 629    {
 630  15 return;
 631    }
 632   
 633    // Trying to stop() from FAILED is valid, but may not work
 634  39 boolean failed = cacheStatus == CacheStatus.FAILED;
 635   
 636  39 try
 637    {
 638  39 int oldState = getState();
 639  39 cacheStatus = CacheStatus.STOPPING;
 640  39 int stoppingState = getState();
 641  39 sendStateChangeNotification(oldState, stoppingState, getClass().getSimpleName() + " stopping", null);
 642   
 643  39 cache.stop();
 644   
 645  38 if (cache.getCacheStatus() == CacheStatus.DESTROYED)
 646    {
 647    // Cache was already destroyed externally;
 648    // so get rid of the interceptor mbeans
 649  0 unregisterInterceptors();
 650    }
 651   
 652  38 cacheStatus = CacheStatus.STOPPED;
 653  38 sendStateChangeNotification(stoppingState, getState(), getClass().getSimpleName() + " stopped", null);
 654    }
 655    catch (Throwable t)
 656    {
 657  1 if (failed)
 658    {
 659  0 log.warn("Attempted to stop() from FAILED state, " +
 660    "but caught exception; try calling destroy()", t);
 661    }
 662  1 handleLifecycleTransitionFailure(t);
 663    }
 664    }
 665   
 666  55 public void destroy()
 667    {
 668  55 if (cacheStatus.destroyAllowed() == false)
 669    {
 670  16 if (cacheStatus.needStopBeforeDestroy())
 671    {
 672  1 try
 673    {
 674  1 stop();
 675    }
 676    catch (CacheException e)
 677    {
 678  0 log.warn("Needed to call stop() before destroying but stop() " +
 679    "threw exception. Proceeding to destroy", e);
 680    }
 681    }
 682    else
 683  15 return;
 684    }
 685   
 686  40 try
 687    {
 688  40 cacheStatus = CacheStatus.DESTROYING;
 689   
 690  40 cache.destroy();
 691   
 692    // The cache is destroyed, so we shouldn't leave the interceptors
 693    // in JMX, even if we didn't register them in create
 694  40 unregisterInterceptors();
 695    }
 696    finally
 697    {
 698    // We always proceed to DESTROYED
 699  40 cacheStatus = CacheStatus.DESTROYED;
 700    }
 701    }
 702   
 703    // ------------------------------------------------------ MBeanRegistration
 704   
 705    /**
 706    * Caches the provided <code>server</code> and <code>objName</code>.
 707    */
 708  71 public ObjectName preRegister(MBeanServer server, ObjectName objName)
 709    throws Exception
 710    {
 711  71 this.server = server;
 712   
 713  71 if (cacheObjectName == null)
 714    {
 715  68 if (objName == null)
 716    {
 717    // Calling this will create a value for cacheObjectName
 718  0 getCacheObjectName();
 719    }
 720    else
 721    {
 722  68 cacheObjectName = objName.getCanonicalName();
 723    }
 724    }
 725   
 726  71 ObjectName result = new ObjectName(cacheObjectName);
 727   
 728    // Inform our CacheNotificationListener of the ObjectName it should transmit
 729  71 if (notificationServiceName == null)
 730  45 notificationServiceName = result.getCanonicalName();
 731  71 cacheNotificationListener.setServiceName(notificationServiceName);
 732   
 733  71 return result;
 734    }
 735   
 736    /**
 737    * Registers the cache's interceptors, if {@link #getRegisterInterceptors()}
 738    * is <code>true</code>.
 739    */
 740  71 public void postRegister(Boolean registrationDone)
 741    {
 742  71 if (Boolean.TRUE.equals(registrationDone))
 743    {
 744  71 log.debug("Registered in JMX under " + cacheObjectName);
 745   
 746  71 if (cache != null && CacheStatus.STARTED.equals(cache.getCacheStatus()))
 747    {
 748  12 try
 749    {
 750  12 registerInterceptors();
 751    }
 752    catch (Exception e)
 753    {
 754  0 log.error("Caught exception registering cache interceptors with JMX", e);
 755    }
 756    }
 757   
 758  71 registered = true;
 759    }
 760    }
 761   
 762    /**
 763    * No-op.
 764    */
 765  71 public void preDeregister() throws Exception
 766    {
 767    }
 768   
 769    /**
 770    * Unregisters the interceptors, if {@link #getRegisterInterceptors()} is
 771    * <code>true</code>.
 772    */
 773  71 public void postDeregister()
 774    {
 775  71 unregisterInterceptors();
 776   
 777  71 server = null;
 778  71 registered = false;
 779    }
 780   
 781    // --------------------------------------------------------- Public methods
 782   
 783    /**
 784    * Sets the configuration that the underlying cache should use.
 785    *
 786    * @param config the configuration
 787    * @throws IllegalArgumentException if <code>config</code> is <code>null</code>.
 788    */
 789  15 public void setConfiguration(Configuration config)
 790    {
 791  15 this.config = config;
 792    }
 793   
 794    /**
 795    * Allows direct injection of the underlying cache.
 796    *
 797    * @param cache
 798    */
 799  71 public void setCache(Cache cache)
 800    {
 801  71 if (cacheStatus != CacheStatus.INSTANTIATED
 802    && cacheStatus != CacheStatus.CREATING
 803    && cacheStatus != CacheStatus.DESTROYED)
 804    {
 805  0 throw new IllegalStateException("Cannot set underlying cache after call to create()");
 806    }
 807   
 808    // FIXME -- having to cast is ugly!!
 809  71 this.cache = (CacheImpl) cache;
 810  71 this.config = (cache == null ? null : cache.getConfiguration());
 811  71 synchronized (listenerCount)
 812    {
 813  71 if (listenerCount.get() > 0)
 814    {
 815  5 cache.addCacheListener(cacheNotificationListener);
 816    }
 817    }
 818    }
 819   
 820  63 public String getCacheObjectName()
 821    {
 822  63 if (cacheObjectName == null)
 823    {
 824  1 cacheObjectName = JmxUtil.getDefaultCacheObjectName(config, CacheImpl.class.getName());
 825    }
 826  63 return cacheObjectName;
 827    }
 828   
 829  3 public void setCacheObjectName(String name) throws MalformedObjectNameException
 830    {
 831  3 if (name != null)
 832    {
 833    // test the name
 834  2 new ObjectName(name);
 835    }
 836  3 this.cacheObjectName = name;
 837    }
 838   
 839    /**
 840    * Gets whether sending of JMX notifications for this mbean's
 841    * start/stop lifecycle changes is disabled.
 842    *
 843    * @see #setDisableStateChangeNotifications(boolean)
 844    */
 845  160 public boolean isDisableStateChangeNotifications()
 846    {
 847  160 return disableStateChangeNotifications;
 848    }
 849   
 850    /**
 851    * Hook to allow PojoCacheJmxWrapper to suppress state change
 852    * notifications from this mbean in lieu of its own.
 853    *
 854    * @param disableStateChangeNotifications
 855    */
 856  29 public void setDisableStateChangeNotifications(boolean disableStateChangeNotifications)
 857    {
 858  29 this.disableStateChangeNotifications = disableStateChangeNotifications;
 859    }
 860   
 861  0 public MBeanServer getMBeanServer()
 862    {
 863  0 return server;
 864    }
 865   
 866    /**
 867    * Formats a given String for display as an HTML snippet.
 868    *
 869    * @param s string to format
 870    * @return formatted string
 871    */
 872  6 public static String formatHtml(String s)
 873    {
 874  6 s = s.replaceAll("\r\n", "<br />");
 875  6 s = s.replaceAll("\r", "<br />");
 876  6 s = s.replaceAll("\n", "<br />");
 877  6 s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
 878  6 s = s.replaceAll(" ", "&nbsp;");
 879  6 return s;
 880    }
 881   
 882  0 public String getNotificationServiceName()
 883    {
 884  0 return notificationServiceName;
 885    }
 886   
 887  28 public void setNotificationServiceName(String notificationServiceName)
 888    {
 889  28 this.notificationServiceName = notificationServiceName;
 890  28 this.cacheNotificationListener.setServiceName(notificationServiceName);
 891    }
 892   
 893  328 public long getNextNotificationSequenceNumber()
 894    {
 895  328 return sequence.getAndIncrement();
 896    }
 897   
 898    // ---------------------------------------------------- Superclass Overrides
 899   
 900  18 @Override
 901    public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object object) throws IllegalArgumentException
 902    {
 903  18 super.addNotificationListener(notificationListener, notificationFilter, object);
 904  18 notificationRegistration(true);
 905    }
 906   
 907  8 @Override
 908    public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException
 909    {
 910  8 super.removeNotificationListener(notificationListener);
 911  8 notificationRegistration(false);
 912    }
 913   
 914  0 @Override
 915    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
 916    {
 917  0 super.removeNotificationListener(listener, filter, handback);
 918  0 notificationRegistration(false);
 919    }
 920   
 921  0 @Override
 922    public MBeanNotificationInfo[] getNotificationInfo()
 923    {
 924  0 return CacheNotificationListener.getNotificationInfo();
 925    }
 926   
 927    // ------------------------------------------------------ Protected Methods
 928   
 929  13 protected void constructCache() throws ConfigurationException
 930    {
 931  13 log.debug("Constructing Cache");
 932  13 setCache(DefaultCacheFactory.getInstance().createCache(config, false));
 933  13 if (multiplexerService != null)
 934    {
 935  1 injectMuxChannel();
 936    }
 937    }
 938   
 939  52 protected boolean registerInterceptors() throws CacheException
 940    {
 941  52 if (registerInterceptors && !interceptorsRegistered && server != null)
 942    {
 943  32 log.debug("Registering interceptors");
 944  32 List<Interceptor> interc = cache.getInterceptorChain();
 945  32 if (interc != null && interc.size() > 0)
 946    {
 947  32 try
 948    {
 949  32 JmxUtil.registerInterceptors(server, interc, cacheObjectName);
 950  32 interceptorsRegistered = true;
 951  32 return true;
 952    }
 953    catch (JMException e)
 954    {
 955  0 throw new CacheException("Failed to register interceptors", e);
 956    }
 957    }
 958    }
 959  20 return false;
 960    }
 961   
 962  111 protected void unregisterInterceptors()
 963    {
 964  111 if (registerInterceptors && interceptorsRegistered && server != null)
 965    {
 966  32 try
 967    {
 968  32 log.debug("Unreqistering interceptors");
 969  32 JmxUtil.unregisterInterceptors(server, cache.getInterceptorChain(), getCacheObjectName());
 970  32 interceptorsRegistered = false;
 971    }
 972    catch (Exception e)
 973    {
 974  0 log.error("Exception unregistering interceptors from JMX", e);
 975    }
 976    }
 977    }
 978   
 979    // -------------------------------------------------------- Private methods
 980   
 981  1 private void injectMuxChannel() throws CacheException
 982    {
 983  1 Configuration cfg = getConfiguration();
 984  1 RuntimeConfig rtcfg = cfg.getRuntimeConfig();
 985   
 986    // Only inject if there isn't already a channel or factory
 987  1 if (rtcfg.getMuxChannelFactory() == null && rtcfg.getChannel() == null)
 988    {
 989  1 Channel ch;
 990  1 try
 991    {
 992  1 ch = multiplexerService.createMultiplexerChannel(cfg.getMultiplexerStack(), cfg.getClusterName());
 993    }
 994    catch (Exception e)
 995    {
 996  0 throw new CacheException("Exception creating multiplexed channel", e);
 997    }
 998  1 rtcfg.setChannel(ch);
 999    }
 1000    }
 1001   
 1002   
 1003    /**
 1004    * Adds and removes the CacheListener.
 1005    * A counter is used to determine whether we have any clients who are
 1006    * registered for notifications from this mbean. When the count is zero,
 1007    * we don't need to listen to cache events, so we remove the CacheListener.
 1008    * Note that a client who terminates without unregistering for notifications
 1009    * will leave the count greater than zero so we'll still listen in that case.
 1010    *
 1011    * @param add <code>true</code> if the event was a listerner addition,
 1012    * <code>false</code> if it was a removal
 1013    */
 1014  26 private void notificationRegistration(boolean add)
 1015    {
 1016    // This method adds and removes the CacheImpl listener.
 1017    // The m_listeners counter is used to determine whether
 1018    // we have any clients who are registered for notifications
 1019    // from this mbean. When the count is zero, we don't need to
 1020    // listen to cache events. Note that a client who terminates
 1021    // without unregistering for notifications will leave the count
 1022    // greater than zero so we'll still listen in that case.
 1023  26 synchronized (listenerCount)
 1024    {
 1025  26 if (add)
 1026    {
 1027  18 listenerCount.incrementAndGet();
 1028  18 if (cache != null)
 1029  13 cache.addCacheListener(cacheNotificationListener);
 1030    }
 1031    else
 1032    {
 1033  8 if (listenerCount.decrementAndGet() <= 0)
 1034    {
 1035  8 if (cache != null)
 1036  8 cache.removeCacheListener(cacheNotificationListener);
 1037   
 1038  8 listenerCount.set(0);
 1039    }
 1040    }
 1041    }
 1042    }
 1043   
 1044    /**
 1045    * Sets the cacheStatus to FAILED and rethrows the problem as one
 1046    * of the declared types. Converts any non-RuntimeException Exception
 1047    * to CacheException.
 1048    *
 1049    * @param t
 1050    * @throws CacheException
 1051    * @throws RuntimeException
 1052    * @throws Error
 1053    */
 1054  2 private void handleLifecycleTransitionFailure(Throwable t)
 1055    throws CacheException, RuntimeException, Error
 1056    {
 1057  2 int oldState = getState();
 1058  2 cacheStatus = CacheStatus.FAILED;
 1059  2 sendStateChangeNotification(oldState, getState(), getClass().getSimpleName() + " failed", t);
 1060   
 1061  2 if (t instanceof CacheException)
 1062  2 throw (CacheException) t;
 1063  0 else if (t instanceof RuntimeException)
 1064  0 throw (RuntimeException) t;
 1065  0 else if (t instanceof Error)
 1066  0 throw (Error) t;
 1067    else
 1068  0 throw new CacheException(t);
 1069    }
 1070   
 1071    /**
 1072    * Helper for sending out state change notifications
 1073    */
 1074  160 private void sendStateChangeNotification(int oldState, int newState, String msg, Throwable t)
 1075    {
 1076  160 if (isDisableStateChangeNotifications())
 1077  66 return;
 1078   
 1079  94 long now = System.currentTimeMillis();
 1080   
 1081  94 AttributeChangeNotification stateChangeNotification = new AttributeChangeNotification(
 1082    this,
 1083    getNextNotificationSequenceNumber(), now, msg,
 1084    "State", "java.lang.Integer",
 1085    new Integer(oldState), new Integer(newState)
 1086    );
 1087  94 stateChangeNotification.setUserData(t);
 1088   
 1089  94 sendNotification(stateChangeNotification);
 1090    }
 1091    }