View Javadoc

1   /***
2    *  Copyright 2003-2008 Luck Consulting Pty Ltd
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package net.sf.ehcache.hibernate;
17  
18  import net.sf.ehcache.CacheManager;
19  import net.sf.ehcache.util.ClassLoaderUtil;
20  
21  
22  import org.hibernate.cache.Cache;
23  import org.hibernate.cache.CacheException;
24  import org.hibernate.cache.CacheProvider;
25  import org.hibernate.cache.Timestamper;
26  
27  import java.net.URL;
28  import java.util.Properties;
29  import java.util.logging.Logger;
30  import java.util.logging.Level;
31  
32  /***
33   * Singleton cache Provider plugin for Hibernate 3.2 and ehcache-1.2. New in this provider is support for
34   * non Serializable keys and values. This provider works as a Singleton. No matter how many Hibernate Configurations
35   * you have, only one ehcache CacheManager is used. See EhCacheProvider for a non-singleton implementation.
36   * <p/>
37   * Ehcache-1.2 also has many other features such as cluster support and listeners, which can be used seamlessly simply
38   * by configurion in ehcache.xml.
39   * <p/>
40   * Use <code>hibernate.cache.provider_class=net.sf.ehcache.hibernate.SingletonEhCacheProvider</code> in the Hibernate configuration
41   * to enable this provider for Hibernate's second level cache.
42   * <p/>
43   * Updated for ehcache-1.2. Note this provider requires ehcache-1.2.jar. Make sure ehcache-1.1.jar or earlier
44   * is not in the classpath or it will not work.
45   * <p/>
46   * See http://ehcache.sf.net for documentation on ehcache
47   * <p/>
48   *
49   * @author Greg Luck
50   * @author Emmanuel Bernard
51   * @version $Id: SingletonEhCacheProvider.java 744 2008-08-16 20:10:49Z gregluck $
52   */
53  public final class SingletonEhCacheProvider implements CacheProvider {
54  
55      /***
56       * The Hibernate system property specifying the location of the ehcache configuration file name.
57       * <p/
58       * If not set, ehcache.xml will be looked for in the root of the classpath.
59       * <p/>
60       * If set to say ehcache-1.xml, ehcache-1.xml will be looked for in the root of the classpath.
61       */
62      public static final String NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
63  
64      private static final Logger LOG = Logger.getLogger(SingletonEhCacheProvider.class.getName());
65  
66      /***
67       * To be backwardly compatible with a lot of Hibernate code out there, allow multiple starts and stops on the
68       * one singleton CacheManager. Keep a count of references to only stop on when only one reference is held.
69       */
70      private static int referenceCount;
71  
72      private CacheManager manager;
73  
74  
75      /***
76       * Builds a Cache.
77       * <p/>
78       * Even though this method provides properties, they are not used.
79       * Properties for EHCache are specified in the ehcache.xml file.
80       * Configuration will be read from ehcache.xml for a cache declaration
81       * where the name attribute matches the name parameter in this builder.
82       *
83       * @param name       the name of the cache. Must match a cache configured in ehcache.xml
84       * @param properties not used
85       * @return a newly built cache will be built and initialised
86       * @throws org.hibernate.cache.CacheException
87       *          inter alia, if a cache of the same name already exists
88       */
89      public final Cache buildCache(String name, Properties properties) throws CacheException {
90          try {
91              net.sf.ehcache.Ehcache cache = manager.getEhcache(name);
92              if (cache == null) {
93                  SingletonEhCacheProvider.LOG.warning("Could not find a specific ehcache configuration for cache named ["
94                          + name + "]; using defaults.");
95                  manager.addCache(name);
96                  cache = manager.getEhcache(name);
97                  SingletonEhCacheProvider.LOG.fine("started EHCache region: " + name);
98              }
99              return new EhCache(cache);
100         } catch (net.sf.ehcache.CacheException e) {
101             throw new CacheException(e);
102         }
103     }
104 
105     /***
106      * Returns the next timestamp.
107      */
108     public final long nextTimestamp() {
109         return Timestamper.next();
110     }
111 
112     /***
113      * Callback to perform any necessary initialization of the underlying cache implementation
114      * during SessionFactory construction.
115      * <p/>
116      *
117      * @param properties current configuration settings.
118      */
119     public final void start(Properties properties) throws CacheException {
120         String configurationResourceName = null;
121         if (properties != null) {
122             configurationResourceName = (String) properties.get(NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME);
123         }
124         if (configurationResourceName == null || configurationResourceName.length() == 0) {
125             manager = CacheManager.create();
126             referenceCount++;
127         } else {
128             if (!configurationResourceName.startsWith("/")) {
129                 configurationResourceName = "/" + configurationResourceName;
130                 if (LOG.isLoggable(Level.FINE)) {
131                     LOG.fine("prepending / to " + configurationResourceName + ". It should be placed in the root"
132                             + "of the classpath rather than in a package.");
133                 }
134             }
135             URL url = loadResource(configurationResourceName);
136             manager = CacheManager.create(url);
137             referenceCount++;
138         }
139     }
140 
141     private URL loadResource(String configurationResourceName) {
142         ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
143         URL url = null;
144         if (standardClassloader != null) {
145             url = standardClassloader.getResource(configurationResourceName);
146         }
147         if (url == null) {
148             url = this.getClass().getResource(configurationResourceName);
149         }
150         if (LOG.isLoggable(Level.FINE)) {
151             LOG.fine("Creating EhCacheProvider from a specified resource: "
152                     + configurationResourceName + " Resolved to URL: " + url);
153         }
154         if (url == null) {
155             if (LOG.isLoggable(Level.WARNING)) {
156                 LOG.warning("A configurationResourceName was set to " + configurationResourceName +
157                         " but the resource could not be loaded from the classpath." +
158                         "Ehcache will configure itself using defaults.");
159             }
160         }
161         return url;
162     }
163 
164     /***
165      * Callback to perform any necessary cleanup of the underlying cache implementation
166      * during SessionFactory.close().
167      */
168     public void stop() {
169         if (manager != null) {
170             referenceCount--;
171             if (referenceCount == 0) {
172                 manager.shutdown();
173             }
174             manager = null;
175         }
176     }
177 
178     /***
179      * Not sure what this is supposed to do.
180      *
181      * @return false to be safe
182      */
183     public final boolean isMinimalPutsEnabledByDefault() {
184         return false;
185     }
186 
187 }