1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
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 java.net.URL;
19 import java.util.Properties;
20
21 import net.sf.ehcache.CacheManager;
22 import net.sf.ehcache.Ehcache;
23 import net.sf.ehcache.hibernate.management.impl.ProviderMBeanRegistrationHelper;
24 import net.sf.ehcache.hibernate.nonstop.NonstopAccessStrategyFactory;
25 import net.sf.ehcache.hibernate.regions.EhcacheQueryResultsRegion;
26 import net.sf.ehcache.hibernate.regions.EhcacheTimestampsRegion;
27 import net.sf.ehcache.hibernate.regions.EhcacheEntityRegion;
28 import net.sf.ehcache.hibernate.regions.EhcacheCollectionRegion;
29 import net.sf.ehcache.hibernate.strategy.EhcacheAccessStrategyFactory;
30 import net.sf.ehcache.hibernate.strategy.EhcacheAccessStrategyFactoryImpl;
31 import net.sf.ehcache.util.ClassLoaderUtil;
32 import net.sf.ehcache.util.Timestamper;
33
34 import org.hibernate.cache.CacheDataDescription;
35 import org.hibernate.cache.CacheException;
36 import org.hibernate.cache.CollectionRegion;
37 import org.hibernate.cache.EntityRegion;
38 import org.hibernate.cache.QueryResultsRegion;
39 import org.hibernate.cache.RegionFactory;
40 import org.hibernate.cache.TimestampsRegion;
41 import org.hibernate.cache.access.AccessType;
42 import org.hibernate.cfg.Settings;
43
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /***
48 * Abstract implementation of an Ehcache specific RegionFactory.
49 *
50 * @author Chris Dennis
51 * @author Greg Luck
52 * @author Emmanuel Bernard
53 * @author Abhishek Sanoujam
54 */
55 abstract class AbstractEhcacheRegionFactory implements RegionFactory {
56
57 /***
58 * The Hibernate system property specifying the location of the ehcache configuration file name.
59 * <p/>
60 * If not set, ehcache.xml will be looked for in the root of the classpath.
61 * <p/>
62 * If set to say ehcache-1.xml, ehcache-1.xml will be looked for in the root of the classpath.
63 */
64 public static final String NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
65
66 private static final Logger LOG = LoggerFactory.getLogger(AbstractEhcacheRegionFactory.class);
67
68 /***
69 * MBean registration helper class instance for Ehcache Hibernate MBeans.
70 */
71 protected final ProviderMBeanRegistrationHelper mbeanRegistrationHelper = new ProviderMBeanRegistrationHelper();
72
73 /***
74 * Ehcache CacheManager that supplied Ehcache instances for this Hibernate RegionFactory.
75 */
76 protected volatile CacheManager manager;
77
78 /***
79 * Settings object for the Hibernate persistence unit.
80 */
81 protected Settings settings;
82
83 /***
84 * {@link EhcacheAccessStrategyFactory} for creating various access strategies
85 */
86 protected final EhcacheAccessStrategyFactory accessStrategyFactory = new NonstopAccessStrategyFactory(
87 new EhcacheAccessStrategyFactoryImpl());
88
89 /***
90 * Whether to optimize for minimals puts or minimal gets.
91 * <p>
92 * Indicates whether when operating in non-strict read/write or read-only mode
93 * Hibernate should optimize the access patterns for minimal puts or minimal gets.
94 * In Ehcache we default to minimal puts since this should have minimal to no
95 * affect on unclustered users, and has great benefit for clustered users.
96 * <p>
97 * This setting can be overridden by setting the "hibernate.cache.use_minimal_puts"
98 * property in the Hibernate configuration.
99 *
100 * @return true, optimize for minimal puts
101 */
102 public boolean isMinimalPutsEnabledByDefault() {
103 return true;
104 }
105
106 /***
107 * {@inheritDoc}
108 */
109 public long nextTimestamp() {
110 return Timestamper.next();
111 }
112
113 /***
114 * {@inheritDoc}
115 */
116 public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException {
117 return new EhcacheEntityRegion(accessStrategyFactory, getCache(regionName), settings, metadata, properties);
118 }
119
120 /***
121 * {@inheritDoc}
122 */
123 public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
124 throws CacheException {
125 return new EhcacheCollectionRegion(accessStrategyFactory, getCache(regionName), settings, metadata, properties);
126 }
127
128 /***
129 * {@inheritDoc}
130 */
131 public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
132 return new EhcacheQueryResultsRegion(accessStrategyFactory, getCache(regionName), properties);
133 }
134
135 /***
136 * {@inheritDoc}
137 */
138 public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
139 return new EhcacheTimestampsRegion(accessStrategyFactory, getCache(regionName), properties);
140 }
141
142 private Ehcache getCache(String name) throws CacheException {
143 try {
144 Ehcache cache = manager.getEhcache(name);
145 if (cache == null) {
146 LOG.warn("Couldn't find a specific ehcache configuration for cache named [" + name + "]; using defaults.");
147 manager.addCache(name);
148 cache = manager.getEhcache(name);
149 LOG.debug("started EHCache region: " + name);
150 }
151 HibernateUtil.validateEhcache(cache);
152 return cache;
153 } catch (net.sf.ehcache.CacheException e) {
154 throw new CacheException(e);
155 }
156
157 }
158
159 /***
160 * Load a resource from the classpath.
161 */
162 protected static URL loadResource(String configurationResourceName) {
163 ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
164 URL url = null;
165 if (standardClassloader != null) {
166 url = standardClassloader.getResource(configurationResourceName);
167 }
168 if (url == null) {
169 url = AbstractEhcacheRegionFactory.class.getResource(configurationResourceName);
170 }
171
172 LOG.debug("Creating EhCacheRegionFactory from a specified resource: {}. Resolved to URL: {}", configurationResourceName, url);
173 if (url == null) {
174
175 LOG.warn("A configurationResourceName was set to {} but the resource could not be loaded from the classpath." +
176 "Ehcache will configure itself using defaults.", configurationResourceName);
177 }
178 return url;
179 }
180
181 /***
182 * Default access-type used when the configured using JPA 2.0 config. JPA 2.0 allows <code>@Cacheable(true)</code> to be attached to an
183 * entity without any access type or usage qualification.
184 * <p>
185 * We are conservative here in specifying {@link AccessType#READ_WRITE} so as to follow the mantra of "do no harm".
186 * <p>
187 * This is a Hibernate 3.5 method.
188 */
189 public AccessType getDefaultAccessType() {
190 return AccessType.READ_WRITE;
191 }
192
193 }