Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 1,032   Methods: 98
NCLOC: 802   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
PojoCacheJmxWrapper.java 58% 77.2% 81.6% 74.2%
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.pojo.jmx;
 23   
 24    import org.apache.commons.logging.Log;
 25    import org.apache.commons.logging.LogFactory;
 26    import org.jboss.cache.CacheException;
 27    import org.jboss.cache.CacheStatus;
 28    import org.jboss.cache.config.BuddyReplicationConfig;
 29    import org.jboss.cache.config.CacheLoaderConfig;
 30    import org.jboss.cache.config.Configuration;
 31    import org.jboss.cache.config.ConfigurationException;
 32    import org.jboss.cache.config.EvictionConfig;
 33    import org.jboss.cache.config.RuntimeConfig;
 34    import org.jboss.cache.factories.XmlConfigurationParser;
 35    import org.jboss.cache.jmx.CacheJmxWrapper;
 36    import org.jboss.cache.jmx.CacheNotificationListener;
 37    import org.jboss.cache.pojo.PojoCache;
 38    import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
 39    import org.jboss.cache.pojo.PojoCacheException;
 40    import org.jboss.cache.pojo.PojoCacheFactory;
 41    import org.jboss.cache.pojo.impl.PojoCacheImpl;
 42    import org.jgroups.Channel;
 43    import org.jgroups.ChannelFactory;
 44    import org.jgroups.jmx.JChannelFactoryMBean;
 45    import org.w3c.dom.Element;
 46   
 47    import javax.management.AttributeChangeNotification;
 48    import javax.management.JMException;
 49    import javax.management.ListenerNotFoundException;
 50    import javax.management.MBeanNotificationInfo;
 51    import javax.management.MBeanRegistration;
 52    import javax.management.MBeanServer;
 53    import javax.management.NotificationEmitter;
 54    import javax.management.NotificationFilter;
 55    import javax.management.NotificationListener;
 56    import javax.management.ObjectName;
 57    import javax.transaction.TransactionManager;
 58    import java.util.HashSet;
 59    import java.util.Iterator;
 60    import java.util.Set;
 61   
 62    public class PojoCacheJmxWrapper
 63    implements PojoCacheJmxWrapperMBean, MBeanRegistration, NotificationEmitter
 64    {
 65    private Log log = LogFactory.getLog(getClass().getName());
 66   
 67    private boolean registerInterceptors = true;
 68    private Configuration config;
 69    private MBeanServer server;
 70    private String cacheObjectName;
 71    private PojoCache pojoCache;
 72    private CacheJmxWrapper plainCacheWrapper;
 73    private boolean registerPlainCache = true;
 74    private boolean plainCacheRegistered;
 75    private CacheStatus cacheStatus;
 76    private boolean registered;
 77    private final Set<NotificationListenerArgs> pendingListeners =
 78    new HashSet<NotificationListenerArgs>();
 79   
 80    // Legacy config support
 81   
 82    private Element buddyReplConfig;
 83    private Element evictionConfig;
 84    private Element cacheLoaderConfig;
 85    private Element clusterConfig;
 86    private JChannelFactoryMBean multiplexerService;
 87   
 88    /**
 89    * Default constructor.
 90    */
 91  33 public PojoCacheJmxWrapper()
 92    {
 93  33 cacheStatus = CacheStatus.INSTANTIATED;
 94    }
 95   
 96    /**
 97    * Creates a PojoCacheJmxWrapper that wraps the given PojoCache.
 98    *
 99    * @param toWrap the cache
 100    */
 101  18 public PojoCacheJmxWrapper(PojoCache toWrap)
 102    {
 103  18 this();
 104  18 setPojoCache(toWrap);
 105    }
 106   
 107    // PojoCacheMBean
 108   
 109  4 public PojoCache getPojoCache()
 110    {
 111  4 return pojoCache;
 112    }
 113   
 114  46 public Configuration getConfiguration()
 115    {
 116  46 Configuration cfg = (pojoCache == null ? config : pojoCache.getCache().getConfiguration());
 117  46 if (cfg == null)
 118    {
 119  2 cfg = config = new Configuration();
 120    }
 121  46 return cfg;
 122    }
 123   
 124  0 public String getInternalLocation(Object pojo) throws PojoCacheAlreadyDetachedException
 125    {
 126  0 return pojoCache.getPojoID(pojo);
 127    }
 128   
 129  1 public String getUnderlyingCacheObjectName()
 130    {
 131  1 return plainCacheWrapper == null ? null : plainCacheWrapper.getCacheObjectName();
 132    }
 133   
 134  19 public void create() throws PojoCacheException
 135    {
 136  19 if (cacheStatus.createAllowed() == false)
 137    {
 138  1 if (cacheStatus.needToDestroyFailedCache())
 139  0 destroy();
 140    else
 141  1 return;
 142    }
 143   
 144  18 try
 145    {
 146  18 cacheStatus = CacheStatus.CREATING;
 147   
 148  18 if (pojoCache == null)
 149    {
 150  11 if (config == null)
 151    {
 152  0 throw new ConfigurationException("Must call setConfiguration() " +
 153    "or setPojoCache() before call to create()");
 154    }
 155   
 156  11 constructCache();
 157    }
 158   
 159  18 pojoCache.create();
 160   
 161  18 registerPlainCache();
 162   
 163  18 plainCacheWrapper.create();
 164   
 165  18 cacheStatus = CacheStatus.CREATED;
 166    }
 167    catch (Throwable t)
 168    {
 169  0 handleLifecycleTransitionFailure(t);
 170    }
 171    }
 172   
 173  19 public void start() throws PojoCacheException
 174    {
 175  19 if (cacheStatus.startAllowed() == false)
 176    {
 177  3 if (cacheStatus.needToDestroyFailedCache())
 178  1 destroy();
 179  3 if (cacheStatus.needCreateBeforeStart())
 180  2 create();
 181    else
 182  1 return;
 183    }
 184   
 185  18 try
 186    {
 187  18 int oldState = getState();
 188  18 cacheStatus = CacheStatus.STARTING;
 189  18 int startingState = getState();
 190  18 sendStateChangeNotification(oldState, startingState, getClass().getSimpleName() + " starting", null);
 191   
 192  18 pojoCache.start();
 193   
 194  17 plainCacheWrapper.start();
 195  17 cacheStatus = CacheStatus.STARTED;
 196  17 sendStateChangeNotification(startingState, getState(), getClass().getSimpleName() + " started", null);
 197    }
 198    catch (Throwable t)
 199    {
 200  1 handleLifecycleTransitionFailure(t);
 201    }
 202    }
 203   
 204  26 public void stop()
 205    {
 206  26 if (cacheStatus.stopAllowed() == false)
 207    {
 208  9 return;
 209    }
 210   
 211    // Trying to stop() from FAILED is valid, but may not work
 212  17 boolean failed = cacheStatus == CacheStatus.FAILED;
 213   
 214  17 try
 215    {
 216  17 int oldState = getState();
 217  17 cacheStatus = CacheStatus.STOPPING;
 218  17 int stoppingState = getState();
 219  17 sendStateChangeNotification(oldState, stoppingState, getClass().getSimpleName() + " stopping", null);
 220   
 221  17 cacheStatus = CacheStatus.STOPPING;
 222   
 223  17 pojoCache.stop();
 224   
 225  16 plainCacheWrapper.stop();
 226  16 cacheStatus = CacheStatus.STOPPED;
 227  16 sendStateChangeNotification(stoppingState, getState(), getClass().getSimpleName() + " stopped", null);
 228    }
 229    catch (Throwable t)
 230    {
 231  1 if (failed)
 232    {
 233  0 log.warn("Attempted to stop() from FAILED state, " +
 234    "but caught exception; try calling destroy()", t);
 235    }
 236  1 handleLifecycleTransitionFailure(t);
 237    }
 238    }
 239   
 240  26 public void destroy()
 241    {
 242  26 if (cacheStatus.destroyAllowed() == false)
 243    {
 244  9 if (cacheStatus.needStopBeforeDestroy())
 245  0 stop();
 246    else
 247  9 return;
 248    }
 249   
 250  17 try
 251    {
 252  17 cacheStatus = CacheStatus.DESTROYING;
 253   
 254  17 pojoCache.destroy();
 255   
 256    // The cache is destroyed, so we shouldn't leave it registered
 257    // in JMX even if we didn't register it in create()
 258  17 unregisterPlainCache();
 259   
 260  17 plainCacheWrapper.destroy();
 261    }
 262    finally
 263    {
 264    // We always proceed to DESTROYED
 265  17 cacheStatus = CacheStatus.DESTROYED;
 266    }
 267    }
 268   
 269  7 public CacheStatus getCacheStatus()
 270    {
 271  7 return cacheStatus;
 272    }
 273   
 274  114 public int getState()
 275    {
 276  114 switch (cacheStatus)
 277    {
 278  2 case INSTANTIATED:
 279  0 case CREATING:
 280  2 return registered ? REGISTERED : UNREGISTERED;
 281  19 case CREATED:
 282  19 return CREATED;
 283  19 case STARTING:
 284  19 return STARTING;
 285  34 case STARTED:
 286  34 return STARTED;
 287  18 case STOPPING:
 288  18 return STOPPING;
 289  17 case STOPPED:
 290  0 case DESTROYING:
 291  17 return STOPPED;
 292  2 case DESTROYED:
 293  2 return registered ? DESTROYED : UNREGISTERED;
 294  3 case FAILED:
 295  0 default:
 296  3 return FAILED;
 297    }
 298    }
 299   
 300  0 public boolean getRegisterPlainCache()
 301    {
 302  0 return registerPlainCache;
 303    }
 304   
 305  4 public void setRegisterPlainCache(boolean registerPlainCache)
 306    {
 307  4 this.registerPlainCache = registerPlainCache;
 308    }
 309   
 310  29 public boolean getRegisterInterceptors()
 311    {
 312  29 return registerInterceptors;
 313    }
 314   
 315  5 public void setRegisterInterceptors(boolean register)
 316    {
 317  5 this.registerInterceptors = register;
 318    }
 319   
 320    // ---------------------------------------------------- LegacyConfiguration
 321   
 322  1 public Element getBuddyReplicationConfig()
 323    {
 324  1 return buddyReplConfig;
 325    }
 326   
 327  1 public Element getCacheLoaderConfig()
 328    {
 329  1 return cacheLoaderConfig;
 330    }
 331   
 332  0 public Element getCacheLoaderConfiguration()
 333    {
 334  0 log.warn("MBean attribute 'CacheLoaderConfiguration' is deprecated; " +
 335    "use 'CacheLoaderConfig'");
 336  0 return getCacheLoaderConfig();
 337    }
 338   
 339  1 public String getCacheMode()
 340    {
 341  1 return getConfiguration().getCacheModeString();
 342    }
 343   
 344  1 public String getClusterName()
 345    {
 346  1 return getConfiguration().getClusterName();
 347    }
 348   
 349  0 public String getClusterProperties()
 350    {
 351  0 return getConfiguration().getClusterConfig();
 352    }
 353   
 354  1 public Element getClusterConfig()
 355    {
 356  1 return clusterConfig;
 357    }
 358   
 359  1 public Element getEvictionPolicyConfig()
 360    {
 361  1 return evictionConfig;
 362    }
 363   
 364  1 public boolean getExposeManagementStatistics()
 365    {
 366  1 return getConfiguration().getExposeManagementStatistics();
 367    }
 368   
 369  0 public boolean getUseInterceptorMbeans()
 370    {
 371  0 log.warn("MBean attribute 'UseInterceptorMbeans' is deprecated; " +
 372    "use 'ExposeManagementStatistics'");
 373  0 return getExposeManagementStatistics();
 374    }
 375   
 376  1 public boolean getFetchInMemoryState()
 377    {
 378  1 return getConfiguration().isFetchInMemoryState();
 379    }
 380   
 381  1 public long getStateRetrievalTimeout()
 382    {
 383  1 return getConfiguration().getStateRetrievalTimeout();
 384    }
 385   
 386  1 @Deprecated
 387    public void setInitialStateRetrievalTimeout(long timeout)
 388    {
 389  1 setStateRetrievalTimeout(timeout);
 390    }
 391   
 392  1 public String getIsolationLevel()
 393    {
 394  1 return getConfiguration().getIsolationLevelString();
 395    }
 396   
 397  1 public long getLockAcquisitionTimeout()
 398    {
 399  1 return getConfiguration().getLockAcquisitionTimeout();
 400    }
 401   
 402  0 public JChannelFactoryMBean getMultiplexerService()
 403    {
 404  0 return multiplexerService;
 405    }
 406   
 407  0 public String getMultiplexerStack()
 408    {
 409  0 return getConfiguration().getMultiplexerStack();
 410    }
 411   
 412  1 public ChannelFactory getMuxChannelFactory()
 413    {
 414  1 return getConfiguration().getRuntimeConfig().getMuxChannelFactory();
 415    }
 416   
 417  1 public String getNodeLockingScheme()
 418    {
 419  1 return getConfiguration().getNodeLockingSchemeString();
 420    }
 421   
 422  1 public long getReplQueueInterval()
 423    {
 424  1 return getConfiguration().getReplQueueInterval();
 425    }
 426   
 427  1 public int getReplQueueMaxElements()
 428    {
 429  1 return getConfiguration().getReplQueueMaxElements();
 430    }
 431   
 432  1 public String getReplicationVersion()
 433    {
 434  1 return getConfiguration().getReplVersionString();
 435    }
 436   
 437  1 public boolean getSyncCommitPhase()
 438    {
 439  1 return getConfiguration().isSyncCommitPhase();
 440    }
 441   
 442  1 public long getSyncReplTimeout()
 443    {
 444  1 return getConfiguration().getSyncReplTimeout();
 445    }
 446   
 447  1 public boolean getSyncRollbackPhase()
 448    {
 449  1 return getConfiguration().isSyncRollbackPhase();
 450    }
 451   
 452  1 public TransactionManager getTransactionManager()
 453    {
 454  1 return getConfiguration().getRuntimeConfig().getTransactionManager();
 455    }
 456   
 457  1 public String getTransactionManagerLookupClass()
 458    {
 459  1 return getConfiguration().getTransactionManagerLookupClass();
 460    }
 461   
 462  1 public boolean getUseRegionBasedMarshalling()
 463    {
 464  1 return getConfiguration().isUseRegionBasedMarshalling();
 465    }
 466   
 467  1 public boolean getUseReplQueue()
 468    {
 469  1 return getConfiguration().isUseReplQueue();
 470    }
 471   
 472  1 public boolean isInactiveOnStartup()
 473    {
 474  1 return getConfiguration().isInactiveOnStartup();
 475    }
 476   
 477  1 public void setBuddyReplicationConfig(Element config)
 478    {
 479  1 BuddyReplicationConfig brc = null;
 480  1 if (config != null)
 481    {
 482  1 brc = XmlConfigurationParser.parseBuddyReplicationConfig(config);
 483    }
 484  1 getConfiguration().setBuddyReplicationConfig(brc);
 485  1 this.buddyReplConfig = config;
 486    }
 487   
 488  1 public void setCacheLoaderConfig(Element cache_loader_config)
 489    {
 490  1 CacheLoaderConfig clc = null;
 491  1 if (cache_loader_config != null)
 492    {
 493  1 clc = XmlConfigurationParser.parseCacheLoaderConfig(cache_loader_config);
 494    }
 495  1 getConfiguration().setCacheLoaderConfig(clc);
 496  1 this.cacheLoaderConfig = cache_loader_config;
 497    }
 498   
 499  0 public void setCacheLoaderConfiguration(Element config)
 500    {
 501  0 log.warn("MBean attribute 'CacheLoaderConfiguration' is deprecated; " +
 502    "use 'CacheLoaderConfig'");
 503  0 setCacheLoaderConfig(config);
 504    }
 505   
 506  1 public void setCacheMode(String mode) throws Exception
 507    {
 508  1 getConfiguration().setCacheModeString(mode);
 509    }
 510   
 511  1 public void setClusterConfig(Element config)
 512    {
 513  1 String props = null;
 514  1 if (config != null)
 515    {
 516  1 props = XmlConfigurationParser.parseClusterConfigXml(config);
 517    }
 518  1 getConfiguration().setClusterConfig(props);
 519  1 this.clusterConfig = config;
 520    }
 521   
 522  1 @Deprecated
 523    public long getInitialStateRetrievalTimeout()
 524    {
 525  1 return getStateRetrievalTimeout();
 526    }
 527   
 528  1 public void setClusterName(String name)
 529    {
 530  1 getConfiguration().setClusterName(name);
 531    }
 532   
 533  0 public void setClusterProperties(String cluster_props)
 534    {
 535  0 getConfiguration().setClusterConfig(cluster_props);
 536    }
 537   
 538  1 public void setEvictionPolicyConfig(Element config)
 539    {
 540  1 EvictionConfig ec = null;
 541  1 if (config != null)
 542    {
 543  1 ec = XmlConfigurationParser.parseEvictionConfig(config);
 544    }
 545  1 getConfiguration().setEvictionConfig(ec);
 546  1 this.evictionConfig = config;
 547    }
 548   
 549  1 public void setExposeManagementStatistics(boolean expose)
 550    {
 551  1 getConfiguration().setExposeManagementStatistics(expose);
 552    }
 553   
 554  0 public void setUseInterceptorMbeans(boolean use)
 555    {
 556  0 log.warn("MBean attribute 'UseInterceptorMbeans' is deprecated; " +
 557    "use 'ExposeManagementStatistics'");
 558  0 setExposeManagementStatistics(use);
 559    }
 560   
 561  1 public void setFetchInMemoryState(boolean flag)
 562    {
 563  1 getConfiguration().setFetchInMemoryState(flag);
 564    }
 565   
 566  1 public void setInactiveOnStartup(boolean inactiveOnStartup)
 567    {
 568  1 getConfiguration().setInactiveOnStartup(inactiveOnStartup);
 569    }
 570   
 571  1 public void setStateRetrievalTimeout(long timeout)
 572    {
 573  1 getConfiguration().setStateRetrievalTimeout(timeout);
 574    }
 575   
 576  1 public void setIsolationLevel(String level)
 577    {
 578  1 getConfiguration().setIsolationLevelString(level);
 579    }
 580   
 581  1 public void setLockAcquisitionTimeout(long timeout)
 582    {
 583  1 getConfiguration().setLockAcquisitionTimeout(timeout);
 584    }
 585   
 586  0 public void setMultiplexerService(JChannelFactoryMBean muxService)
 587    {
 588  0 this.multiplexerService = muxService;
 589    }
 590   
 591  0 public void setMultiplexerStack(String stackName)
 592    {
 593  0 getConfiguration().setMultiplexerStack(stackName);
 594    }
 595   
 596  1 public void setMuxChannelFactory(ChannelFactory factory)
 597    {
 598  1 getConfiguration().getRuntimeConfig().setMuxChannelFactory(factory);
 599    }
 600   
 601  1 public void setNodeLockingScheme(String nodeLockingScheme)
 602    {
 603  1 getConfiguration().setNodeLockingSchemeString(nodeLockingScheme);
 604    }
 605   
 606  1 public void setReplQueueInterval(long interval)
 607    {
 608  1 getConfiguration().setReplQueueInterval(interval);
 609    }
 610   
 611  1 public void setReplQueueMaxElements(int max_elements)
 612    {
 613  1 getConfiguration().setReplQueueMaxElements(max_elements);
 614    }
 615   
 616  1 public void setReplicationVersion(String version)
 617    {
 618  1 getConfiguration().setReplVersionString(version);
 619    }
 620   
 621  1 public void setSyncCommitPhase(boolean sync_commit_phase)
 622    {
 623  1 getConfiguration().setSyncCommitPhase(sync_commit_phase);
 624    }
 625   
 626  1 public void setSyncReplTimeout(long timeout)
 627    {
 628  1 getConfiguration().setSyncReplTimeout(timeout);
 629    }
 630   
 631  1 public void setSyncRollbackPhase(boolean sync_rollback_phase)
 632    {
 633  1 getConfiguration().setSyncRollbackPhase(sync_rollback_phase);
 634    }
 635   
 636  1 public void setTransactionManager(TransactionManager manager)
 637    {
 638  1 getConfiguration().getRuntimeConfig().setTransactionManager(manager);
 639    }
 640   
 641  1 public void setTransactionManagerLookupClass(String cl) throws Exception
 642    {
 643  1 getConfiguration().setTransactionManagerLookupClass(cl);
 644    }
 645   
 646  1 public void setUseRegionBasedMarshalling(boolean isTrue)
 647    {
 648  1 getConfiguration().setUseRegionBasedMarshalling(isTrue);
 649    }
 650   
 651  1 public void setUseReplQueue(boolean flag)
 652    {
 653  1 getConfiguration().setUseReplQueue(flag);
 654    }
 655   
 656    // ------------------------------------------------------ MBeanRegistration
 657   
 658    /**
 659    * Caches the provided <code>server</code> and <code>objName</code>.
 660    */
 661  32 public ObjectName preRegister(MBeanServer server, ObjectName objName)
 662    throws Exception
 663    {
 664  32 this.server = server;
 665   
 666  32 if (cacheObjectName == null)
 667    {
 668  32 cacheObjectName = objName.getCanonicalName();
 669    }
 670   
 671  32 if (plainCacheWrapper != null)
 672  23 plainCacheWrapper.setNotificationServiceName(cacheObjectName);
 673   
 674  32 return new ObjectName(cacheObjectName);
 675    }
 676   
 677    /**
 678    * Registers the CacheJmxWrapperMBean,
 679    * if {@link #getRegisterPlainCache()} is <code>true</code>.
 680    */
 681  32 public void postRegister(Boolean registrationDone)
 682    {
 683  32 if (Boolean.TRUE.equals(registrationDone) && registerPlainCache)
 684    {
 685  28 log.debug("Registered in JMX under " + cacheObjectName);
 686   
 687  28 if (plainCacheWrapper != null)
 688    {
 689  21 try
 690    {
 691  21 registerPlainCache();
 692    }
 693    catch (Exception e)
 694    {
 695  0 log.error("Caught exception registering plain cache with JMX", e);
 696    }
 697    }
 698   
 699  28 registered = true;
 700    }
 701    }
 702   
 703    /**
 704    * No-op.
 705    */
 706  32 public void preDeregister() throws Exception
 707    {
 708    }
 709   
 710    /**
 711    * Unregisters the CacheJmxWrapper, if {@link #getRegisterPlainCache()} is
 712    * <code>true</code>.
 713    */
 714  32 public void postDeregister()
 715    {
 716  32 if (plainCacheWrapper != null)
 717    {
 718  28 unregisterPlainCache();
 719    }
 720   
 721  32 registered = false;
 722    }
 723   
 724    // ---------------------------------------------------- NotificationEmitter
 725   
 726  0 public void removeNotificationListener(NotificationListener listener,
 727    NotificationFilter filter,
 728    Object handback)
 729    throws ListenerNotFoundException
 730    {
 731  0 synchronized (pendingListeners)
 732    {
 733  0 boolean found = pendingListeners.remove(new NotificationListenerArgs(listener, filter, handback));
 734   
 735  0 if (plainCacheWrapper != null)
 736    {
 737  0 plainCacheWrapper.removeNotificationListener(listener, filter, handback);
 738    }
 739  0 else if (!found)
 740    {
 741  0 throw new ListenerNotFoundException();
 742    }
 743    }
 744    }
 745   
 746  7 public void addNotificationListener(NotificationListener listener,
 747    NotificationFilter filter,
 748    Object handback)
 749    throws IllegalArgumentException
 750    {
 751  7 synchronized (pendingListeners)
 752    {
 753  7 if (plainCacheWrapper != null)
 754    {
 755  6 plainCacheWrapper.addNotificationListener(listener, filter, handback);
 756    }
 757    else
 758    {
 759    // Add it for addition to the plainCacheWrapper when it's created
 760  1 pendingListeners.add(new NotificationListenerArgs(listener, filter, handback));
 761    }
 762    }
 763   
 764    }
 765   
 766  0 public MBeanNotificationInfo[] getNotificationInfo()
 767    {
 768  0 return CacheNotificationListener.getNotificationInfo();
 769    }
 770   
 771  4 public void removeNotificationListener(NotificationListener listener)
 772    throws ListenerNotFoundException
 773    {
 774  4 synchronized (pendingListeners)
 775    {
 776  4 boolean found = false;
 777  4 for (Iterator<NotificationListenerArgs> iter = pendingListeners.iterator();
 778  4 iter.hasNext();)
 779    {
 780  0 NotificationListenerArgs args = iter.next();
 781  0 if (safeEquals(listener, args.listener))
 782    {
 783  0 found = true;
 784  0 iter.remove();
 785    }
 786    }
 787   
 788  4 if (plainCacheWrapper != null)
 789    {
 790  4 plainCacheWrapper.removeNotificationListener(listener);
 791    }
 792  0 else if (!found)
 793    {
 794  0 throw new ListenerNotFoundException();
 795    }
 796   
 797    }
 798    }
 799   
 800    // --------------------------------------------------------- Public methods
 801   
 802  0 public MBeanServer getMBeanServer()
 803    {
 804  0 return server;
 805    }
 806   
 807    /**
 808    * Sets the configuration that the underlying cache should use.
 809    *
 810    * @param config the configuration
 811    */
 812  13 public void setConfiguration(Configuration config)
 813    {
 814  13 this.config = config;
 815    }
 816   
 817  18 public void setPojoCache(PojoCache cache)
 818    {
 819  18 if (cacheStatus != CacheStatus.INSTANTIATED
 820    && cacheStatus != CacheStatus.DESTROYED)
 821  0 throw new IllegalStateException("Cannot set underlying cache after call to create()");
 822   
 823  18 this.pojoCache = cache;
 824  18 if (pojoCache == null)
 825    {
 826  0 this.config = null;
 827  0 this.plainCacheWrapper = null;
 828    }
 829    else
 830    {
 831  18 this.config = cache.getCache().getConfiguration();
 832  18 this.plainCacheWrapper = buildPlainCacheWrapper(pojoCache);
 833    }
 834    }
 835   
 836    // --------------------------------------------------------------- Private methods
 837   
 838  11 private void constructCache() throws ConfigurationException
 839    {
 840  11 pojoCache = (PojoCacheImpl) PojoCacheFactory.createCache(config, false);
 841   
 842  11 plainCacheWrapper = buildPlainCacheWrapper(pojoCache);
 843  11 if (multiplexerService != null)
 844    {
 845  0 injectMuxChannel();
 846    }
 847    }
 848   
 849  29 private CacheJmxWrapper buildPlainCacheWrapper(PojoCache pojoCache)
 850    {
 851  29 CacheJmxWrapper plainCache = new CacheJmxWrapper();
 852  29 plainCache.setRegisterInterceptors(getRegisterInterceptors());
 853  29 plainCache.setCache(pojoCache.getCache());
 854    // It shouldn't send out lifecycle state change notifications for itself;
 855    // we do it
 856  29 plainCache.setDisableStateChangeNotifications(true);
 857   
 858  29 if (server != null)
 859    {
 860  5 plainCache.setNotificationServiceName(cacheObjectName);
 861    }
 862   
 863    // Add any NotificationListeners we registered before creating
 864    // the CacheJmxWrapper
 865  29 synchronized (pendingListeners)
 866    {
 867  29 for (NotificationListenerArgs args : pendingListeners)
 868    {
 869  1 plainCache.addNotificationListener(args.listener, args.filter, args.handback);
 870    }
 871    }
 872  29 return plainCache;
 873    }
 874   
 875  39 private boolean registerPlainCache() throws CacheException
 876    {
 877  39 if (registerPlainCache && !plainCacheRegistered && server != null)
 878    {
 879  26 try
 880    {
 881  26 ObjectName ourName = new ObjectName(cacheObjectName);
 882  26 ObjectName plainName = JmxUtil.getPlainCacheObjectName(ourName);
 883  26 log.debug("Registering plain cache under name " + plainName.getCanonicalName());
 884  26 org.jboss.cache.jmx.JmxUtil.registerCacheMBean(server, plainCacheWrapper, plainName.getCanonicalName());
 885  26 plainCacheRegistered = true;
 886  26 return true;
 887    }
 888    catch (JMException e)
 889    {
 890  0 throw new CacheException("Failed to register plain cache", e);
 891    }
 892    }
 893   
 894  13 return false;
 895    }
 896   
 897  45 private void unregisterPlainCache()
 898    {
 899  45 if (registerPlainCache && plainCacheRegistered && server != null)
 900    {
 901  26 log.debug("Unregistering plain cache");
 902  26 try
 903    {
 904  26 org.jboss.cache.jmx.JmxUtil.unregisterCacheMBean(server, plainCacheWrapper.getCacheObjectName());
 905    }
 906    catch (Exception e)
 907    {
 908  0 log.error("Could not unregister plain cache", e);
 909    }
 910  26 plainCacheRegistered = false;
 911    }
 912    }
 913   
 914  0 private void injectMuxChannel() throws CacheException
 915    {
 916  0 Configuration cfg = getConfiguration();
 917  0 RuntimeConfig rtcfg = cfg.getRuntimeConfig();
 918   
 919    // Only inject if there isn't already a channel or factory
 920  0 if (rtcfg.getMuxChannelFactory() != null && rtcfg.getChannel() != null)
 921    {
 922  0 Channel ch;
 923  0 try
 924    {
 925  0 ch = multiplexerService.createMultiplexerChannel(cfg.getMultiplexerStack(), cfg.getClusterName());
 926    }
 927    catch (Exception e)
 928    {
 929  0 throw new CacheException("Exception creating multiplexed channel", e);
 930    }
 931  0 rtcfg.setChannel(ch);
 932    }
 933   
 934    }
 935   
 936    /**
 937    * Helper for sending out state change notifications
 938    */
 939  70 private void sendStateChangeNotification(int oldState, int newState, String msg, Throwable t)
 940    {
 941  70 long now = System.currentTimeMillis();
 942   
 943  70 AttributeChangeNotification stateChangeNotification = new AttributeChangeNotification(
 944    this,
 945    plainCacheWrapper.getNextNotificationSequenceNumber(), now, msg,
 946    "State", "java.lang.Integer",
 947    new Integer(oldState), new Integer(newState)
 948    );
 949  70 stateChangeNotification.setUserData(t);
 950   
 951  70 plainCacheWrapper.sendNotification(stateChangeNotification);
 952    }
 953   
 954    /**
 955    * Sets the cacheStatus to FAILED and rethrows the problem as one
 956    * of the declared types. Converts any non-RuntimeException Exception
 957    * to CacheException.
 958    *
 959    * @param t
 960    * @throws PojoCacheException
 961    * @throws RuntimeException
 962    * @throws Error
 963    */
 964  2 private void handleLifecycleTransitionFailure(Throwable t)
 965    throws PojoCacheException, RuntimeException, Error
 966    {
 967  2 int oldState = getState();
 968  2 cacheStatus = CacheStatus.FAILED;
 969  2 sendStateChangeNotification(oldState, getState(), getClass().getSimpleName() + " failed", t);
 970   
 971  2 if (t instanceof PojoCacheException)
 972  1 throw (PojoCacheException) t;
 973  1 if (t instanceof CacheException)
 974  1 throw (CacheException) t;
 975  0 else if (t instanceof RuntimeException)
 976  0 throw (RuntimeException) t;
 977  0 else if (t instanceof Error)
 978  0 throw (Error) t;
 979    else
 980  0 throw new PojoCacheException(t);
 981    }
 982   
 983  0 private static boolean safeEquals(Object us, Object them)
 984    {
 985  0 return (us == null ? them == null : us.equals(them));
 986    }
 987   
 988    private static class NotificationListenerArgs
 989    {
 990    NotificationListener listener;
 991    NotificationFilter filter;
 992    Object handback;
 993   
 994  1 NotificationListenerArgs(NotificationListener listener,
 995    NotificationFilter filter,
 996    Object handback)
 997    {
 998  1 this.listener = listener;
 999  1 this.filter = filter;
 1000  1 this.handback = handback;
 1001    }
 1002   
 1003  0 @Override
 1004    public boolean equals(Object obj)
 1005    {
 1006  0 if (this == obj) return true;
 1007   
 1008  0 if (obj instanceof NotificationListenerArgs)
 1009    {
 1010  0 NotificationListenerArgs other = (NotificationListenerArgs) obj;
 1011  0 if (safeEquals(listener, other.listener)
 1012    && safeEquals(filter, other.filter)
 1013    && safeEquals(handback, other.handback))
 1014    {
 1015  0 return true;
 1016    }
 1017    }
 1018  0 return false;
 1019    }
 1020   
 1021  1 @Override
 1022    public int hashCode()
 1023    {
 1024  1 int result = 17;
 1025  1 result = 29 * result + (listener != null ? listener.hashCode() : 0);
 1026  1 result = 29 * result + (filter != null ? filter.hashCode() : 0);
 1027  1 result = 29 * result + (handback != null ? handback.hashCode() : 0);
 1028  1 return result;
 1029    }
 1030    }
 1031   
 1032    }