AbstractCacheableService.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.portal.service.cache;

  35. import fr.paris.lutece.portal.service.util.AppLogService;

  36. import net.sf.ehcache.Cache;
  37. import net.sf.ehcache.CacheException;
  38. import net.sf.ehcache.Ehcache;
  39. import net.sf.ehcache.Element;
  40. import net.sf.ehcache.Statistics;
  41. import net.sf.ehcache.event.CacheEventListener;

  42. import java.util.ArrayList;
  43. import java.util.List;

  44. import org.apache.logging.log4j.LogManager;
  45. import org.apache.logging.log4j.Logger;

  46. /**
  47.  * Base implementation for a cacheable service
  48.  */
  49. public abstract class AbstractCacheableService implements CacheableService, CacheEventListener
  50. {
  51.     private Cache _cache;
  52.     private boolean _bEnable;
  53.     private Logger _logger = LogManager.getLogger( "lutece.cache" );

  54.     /**
  55.      * Init the cache. Should be called by the service at its initialization.
  56.      */
  57.     public void initCache( )
  58.     {
  59.         initCache( getName( ) );
  60.     }

  61.     /**
  62.      * Init the cache. Should be called by the service at its initialization.
  63.      *
  64.      * @param strCacheName
  65.      *            The cache name
  66.      */
  67.     public void initCache( String strCacheName )
  68.     {
  69.         createCache( strCacheName );
  70.         _bEnable = true;
  71.         CacheService.registerCacheableService( this );
  72.     }

  73.     /**
  74.      * Create a cache
  75.      *
  76.      * @param strCacheName
  77.      *            The cache name
  78.      */
  79.     private void createCache( String strCacheName )
  80.     {
  81.         _cache = CacheService.getInstance( ).createCache( strCacheName );
  82.         _cache.getCacheEventNotificationService( ).registerListener( this );
  83.     }

  84.     /**
  85.      * Put an object into the cache
  86.      *
  87.      * @param strKey
  88.      *            The key of the object to put into the cache
  89.      * @param object
  90.      *            The object to put into the cache
  91.      */
  92.     public void putInCache( String strKey, Object object )
  93.     {
  94.         if ( ( _cache != null ) && isCacheEnable( ) )
  95.         {
  96.             Element element = new Element( strKey, object );
  97.             _cache.put( element );
  98.         }
  99.     }

  100.     /**
  101.      * Gets an object from the cache
  102.      *
  103.      * @param strKey
  104.      *            The key of the object to retrieve from the cache
  105.      * @return The object from the cache
  106.      */
  107.     public Object getFromCache( String strKey )
  108.     {
  109.         Object object = null;

  110.         if ( ( _cache != null ) && isCacheEnable( ) )
  111.         {
  112.             Element element = _cache.get( strKey );

  113.             if ( element != null )
  114.             {
  115.                 object = element.getObjectValue( );
  116.             }
  117.         }

  118.         return object;
  119.     }

  120.     /**
  121.      * Gets the current cache status.
  122.      *
  123.      * @return true if enable, otherwise false
  124.      */
  125.     @Override
  126.     public boolean isCacheEnable( )
  127.     {
  128.         return _bEnable;
  129.     }

  130.     /**
  131.      * {@inheritDoc }
  132.      */
  133.     @Override
  134.     public void enableCache( boolean bEnable )
  135.     {
  136.         _bEnable = bEnable;

  137.         if ( ( !_bEnable ) && ( _cache != null ) )
  138.         {
  139.             _cache.removeAll( );
  140.         }

  141.         if ( ( _bEnable ) && ( _cache == null ) )
  142.         {
  143.             createCache( getName( ) );
  144.         }

  145.         CacheService.updateCacheStatus( this );
  146.     }

  147.     /**
  148.      * Reset the cache.
  149.      */
  150.     @Override
  151.     public void resetCache( )
  152.     {
  153.         try
  154.         {
  155.             if ( _cache != null )
  156.             {
  157.                 _cache.removeAll( );
  158.             }
  159.         }
  160.         catch( CacheException | IllegalStateException e )
  161.         {
  162.             AppLogService.error( e.getMessage( ), e );
  163.         }
  164.     }

  165.     /**
  166.      * Gets the number of item currently in the cache.
  167.      *
  168.      * @return the number of item currently in the cache.
  169.      */
  170.     @Override
  171.     public int getCacheSize( )
  172.     {
  173.         return ( _cache != null ) ? _cache.getSize( ) : 0;
  174.     }

  175.     /**
  176.      * Return a cache object
  177.      *
  178.      * @return cache object
  179.      */
  180.     public Cache getCache( )
  181.     {
  182.         return _cache;
  183.     }

  184.     /**
  185.      * {@inheritDoc }
  186.      */
  187.     @Override
  188.     public List<String> getKeys( )
  189.     {
  190.         if ( _cache != null )
  191.         {
  192.             return _cache.getKeys( );
  193.         }

  194.         return new ArrayList<>( );
  195.     }

  196.     /**
  197.      * {@inheritDoc }
  198.      */
  199.     @Override
  200.     public int getMaxElements( )
  201.     {
  202.         return _cache.getCacheConfiguration( ).getMaxElementsInMemory( );
  203.     }

  204.     /**
  205.      * {@inheritDoc }
  206.      */
  207.     @Override
  208.     public long getTimeToLive( )
  209.     {
  210.         return _cache.getCacheConfiguration( ).getTimeToLiveSeconds( );
  211.     }

  212.     /**
  213.      * {@inheritDoc }
  214.      */
  215.     @Override
  216.     public long getMemorySize( )
  217.     {
  218.         return _cache.calculateInMemorySize( );
  219.     }

  220.     /**
  221.      * {@inheritDoc }
  222.      */
  223.     @Override
  224.     public String getInfos( )
  225.     {
  226.         return CacheService.getInfos( _cache );
  227.     }

  228.     /**
  229.      * Get cache statistics.
  230.      *
  231.      * The string representation is susceptible to change
  232.      *
  233.      * @return a string representation of cache statistics
  234.      *
  235.      * @since 7.0.10
  236.      */
  237.     public String getStatistics( )
  238.     {
  239.         if ( !( isCacheEnable( ) && _cache.getCacheConfiguration( ).getStatistics( ) ) )
  240.         {
  241.             return null;
  242.         }
  243.         Statistics stats = _cache.getStatistics( );
  244.         StringBuilder buidler = new StringBuilder( );
  245.         buidler.append( "name = " ).append( stats.getAssociatedCacheName( ) ).append( "\ncacheHits = " )
  246.                 .append( stats.getCacheHits( ) ).append( "\nonDiskHits = " ).append( stats.getOnDiskHits( ) )
  247.                 .append( "\noffHeapHits = " ).append( stats.getOffHeapHits( ) ).append( "\ninMemoryHits = " )
  248.                 .append( stats.getInMemoryHits( ) ).append( "\nmisses = " ).append( stats.getCacheMisses( ) )
  249.                 .append( "\nonDiskMisses = " ).append( stats.getOnDiskMisses( ) ).append( "\noffHeapMisses = " )
  250.                 .append( stats.getOffHeapMisses( ) ).append( "\ninMemoryMisses = " )
  251.                 .append( stats.getInMemoryMisses( ) ).append( "\nsize = " ).append( stats.getObjectCount( ) )
  252.                 .append( "\naverageGetTime = " ).append( stats.getAverageGetTime( ) ).append( "\nevictionCount = " )
  253.                 .append( stats.getEvictionCount( ) );
  254.         return buidler.toString( );
  255.     }

  256.     // CacheEventListener implementation

  257.     /**
  258.      * @see java.lang.Object#clone()
  259.      * @return the instance
  260.      */
  261.     @Override
  262.     public Object clone( )
  263.     {
  264.         throw new UnsupportedOperationException( "This class shouldn't be cloned" );
  265.     }

  266.     /**
  267.      * {@inheritDoc }
  268.      */
  269.     @Override
  270.     public void notifyElementExpired( Ehcache cache, Element element )
  271.     {
  272.         // Remove the element from the cache
  273.         _cache.remove( element.getKey( ) );
  274.         _logger.debug( "Object removed from the cache : {}  - key : {}", cache.getName( ), element.getKey( ) );
  275.     }

  276.     /**
  277.      * {@inheritDoc }
  278.      */
  279.     @Override
  280.     public void notifyElementRemoved( Ehcache ehch, Element elmnt )
  281.     {
  282.         // Do nothing
  283.     }

  284.     /**
  285.      * {@inheritDoc }
  286.      */
  287.     @Override
  288.     public void notifyElementEvicted( Ehcache ehch, Element elmnt )
  289.     {
  290.         // Do nothing
  291.     }

  292.     /**
  293.      * {@inheritDoc }
  294.      */
  295.     @Override
  296.     public void notifyRemoveAll( Ehcache ehch )
  297.     {
  298.         // Do nothing
  299.     }

  300.     /**
  301.      * {@inheritDoc }
  302.      */
  303.     @Override
  304.     public void notifyElementPut( Ehcache ehch, Element elmnt )
  305.     {
  306.         // Do nothing
  307.     }

  308.     /**
  309.      * {@inheritDoc }
  310.      */
  311.     @Override
  312.     public void notifyElementUpdated( Ehcache ehch, Element elmnt )
  313.     {
  314.         // Do nothing
  315.     }

  316.     /**
  317.      * {@inheritDoc }
  318.      */
  319.     @Override
  320.     public void dispose( )
  321.     {
  322.         // Do nothing
  323.     }

  324.     /**
  325.      * Remove a key from the cache
  326.      *
  327.      * @param strKey
  328.      *            The key to remove
  329.      */
  330.     public void removeKey( String strKey )
  331.     {
  332.         getCache( ).remove( strKey );
  333.     }
  334. }