1 19 package org.apache.cayenne.cache; 20 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Properties ; 28 29 import org.apache.cayenne.CayenneRuntimeException; 30 import org.apache.cayenne.query.QueryMetadata; 31 32 import com.opensymphony.oscache.base.CacheEntry; 33 import com.opensymphony.oscache.base.NeedsRefreshException; 34 import com.opensymphony.oscache.general.GeneralCacheAdministrator; 35 36 78 public class OSQueryCache implements QueryCache { 79 80 public static final int DEFAULT_REFRESH_PERIOD = CacheEntry.INDEFINITE_EXPIRY; 81 82 static String DEFAULT_REFRESH_KEY = "cayenne.default.refresh"; 83 static String DEFAULT_CRON_KEY = "cayenne.default.cron"; 84 85 static String GROUP_PREFIX = "cayenne.group."; 86 static String REFRESH_SUFFIX = ".refresh"; 87 static String CRON_SUFFIX = ".cron"; 88 89 protected GeneralCacheAdministrator osCache; 90 91 RefreshSpecification defaultRefreshSpecification; 92 Map refreshSpecifications; 93 Properties properties; 94 95 public OSQueryCache() { 96 OSCacheAdministrator admin = new OSCacheAdministrator(); 97 init(admin, admin.getProperties()); 98 } 99 100 public OSQueryCache(GeneralCacheAdministrator cache, Properties properties) { 101 init(cache, properties); 102 } 103 104 108 public Collection getGroupNames() { 109 return refreshSpecifications != null 110 ? Collections.unmodifiableCollection(refreshSpecifications.keySet()) 111 : Collections.EMPTY_SET; 112 } 113 114 public String getCronExpression(String groupName) { 115 116 RefreshSpecification spec = null; 117 118 if (refreshSpecifications != null) { 119 spec = (RefreshSpecification) refreshSpecifications.get(groupName); 120 } 121 122 if (spec == null) { 123 spec = defaultRefreshSpecification; 124 } 125 126 return spec.cronExpression; 127 } 128 129 public int getRrefreshPeriod(String groupName) { 130 131 RefreshSpecification spec = null; 132 133 if (refreshSpecifications != null) { 134 spec = (RefreshSpecification) refreshSpecifications.get(groupName); 135 } 136 137 if (spec == null) { 138 spec = defaultRefreshSpecification; 139 } 140 141 return spec.refreshPeriod; 142 } 143 144 147 public GeneralCacheAdministrator getOsCache() { 148 return osCache; 149 } 150 151 155 public Properties getProperties() { 156 return properties; 157 } 158 159 void init(GeneralCacheAdministrator cache, Properties properties) { 160 this.properties = properties; 161 this.osCache = cache; 162 this.defaultRefreshSpecification = new RefreshSpecification(); 163 164 if (properties != null) { 166 167 String defaultRefresh = properties.getProperty(DEFAULT_REFRESH_KEY); 169 if (defaultRefresh != null) { 170 defaultRefreshSpecification.setRefreshPeriod(defaultRefresh); 171 } 172 173 String defaultCron = properties.getProperty(DEFAULT_CRON_KEY); 174 if (defaultCron != null) { 175 defaultRefreshSpecification.cronExpression = defaultCron; 176 } 177 178 Iterator it = properties.entrySet().iterator(); 180 while (it.hasNext()) { 181 182 Map.Entry entry = (Map.Entry ) it.next(); 183 184 if (entry.getKey() == null || entry.getValue() == null) { 185 continue; 186 } 187 188 String key = entry.getKey().toString(); 189 if (key.startsWith(GROUP_PREFIX)) { 190 191 if (key.endsWith(REFRESH_SUFFIX)) { 192 String name = key.substring(GROUP_PREFIX.length(), key.length() 193 - REFRESH_SUFFIX.length()); 194 195 initRefreshPolicy(name, entry.getValue()); 196 } 197 else if (key.endsWith(CRON_SUFFIX)) { 198 String name = key.substring(GROUP_PREFIX.length(), key.length() 199 - CRON_SUFFIX.length()); 200 201 initCronPolicy(name, entry.getValue()); 202 } 203 } 204 } 205 } 206 } 207 208 213 protected void initCronPolicy(String groupName, Object value) { 214 nonNullSpec(groupName).cronExpression = value != null ? value.toString() : null; 215 } 216 217 222 protected void initRefreshPolicy(String groupName, Object value) { 223 nonNullSpec(groupName).setRefreshPeriod(value); 224 } 225 226 private RefreshSpecification nonNullSpec(String name) { 227 if (refreshSpecifications == null) { 228 refreshSpecifications = new HashMap (); 229 } 230 231 RefreshSpecification spec = (RefreshSpecification) refreshSpecifications 232 .get(name); 233 if (spec == null) { 234 spec = new RefreshSpecification(); 235 spec.cronExpression = defaultRefreshSpecification.cronExpression; 236 spec.refreshPeriod = defaultRefreshSpecification.refreshPeriod; 237 refreshSpecifications.put(name, spec); 238 } 239 240 return spec; 241 } 242 243 public List get(QueryMetadata metadata) { 244 String key = metadata.getCacheKey(); 245 if (key == null) { 246 return null; 247 } 248 249 RefreshSpecification refresh = getRefreshSpecification(metadata); 250 251 try { 252 return (List ) osCache.getFromCache( 253 key, 254 refresh.refreshPeriod, 255 refresh.cronExpression); 256 } 257 catch (NeedsRefreshException e) { 258 osCache.cancelUpdate(key); 259 return null; 260 } 261 } 262 263 269 public List get(QueryMetadata metadata, QueryCacheEntryFactory factory) { 270 String key = metadata.getCacheKey(); 271 if (key == null) { 272 return null; 273 } 274 275 RefreshSpecification refresh = getRefreshSpecification(metadata); 276 277 try { 278 return (List ) osCache.getFromCache( 279 key, 280 refresh.refreshPeriod, 281 refresh.cronExpression); 282 } 283 catch (NeedsRefreshException e) { 284 boolean updated = false; 285 try { 286 Object result = factory.createObject(); 287 288 if (!(result instanceof List )) { 289 if (result == null) { 290 throw new CayenneRuntimeException("Null on cache rebuilding: " 291 + metadata.getCacheKey()); 292 } 293 else { 294 throw new CayenneRuntimeException( 295 "Invalid query result, expected List, got " 296 + result.getClass().getName()); 297 } 298 } 299 300 List list = (List ) result; 301 302 put(metadata, list); 303 updated = true; 304 return list; 305 } 306 finally { 307 if (!updated) { 308 osCache.cancelUpdate(key); 311 } 312 } 313 } 314 } 315 316 319 RefreshSpecification getRefreshSpecification(QueryMetadata metadata) { 320 321 RefreshSpecification refresh = null; 322 323 if (refreshSpecifications != null) { 324 String [] groups = metadata.getCacheGroups(); 325 if (groups != null && groups.length > 0) { 326 refresh = (RefreshSpecification) refreshSpecifications.get(groups[0]); 327 } 328 } 329 330 return refresh != null ? refresh : defaultRefreshSpecification; 331 } 332 333 public void put(QueryMetadata metadata, List results) { 334 String key = metadata.getCacheKey(); 335 if (key != null) { 336 osCache.putInCache(key, results, metadata.getCacheGroups()); 337 } 338 } 339 340 public void remove(String key) { 341 if (key != null) { 342 osCache.removeEntry(key); 343 } 344 } 345 346 public void removeGroup(String groupKey) { 347 if (groupKey != null) { 348 osCache.flushGroup(groupKey); 349 } 350 } 351 352 public void clear() { 353 osCache.flushAll(); 354 } 355 356 public int size() { 357 return osCache.getCache().getSize(); 358 } 359 360 public int capacity() { 361 return osCache.getCache().getCapacity(); 362 } 363 364 final static class RefreshSpecification { 365 366 int refreshPeriod; 367 String cronExpression; 368 369 RefreshSpecification() { 370 this.refreshPeriod = DEFAULT_REFRESH_PERIOD; 371 } 372 373 RefreshSpecification(int refrehsPeriod, String cronExpression) { 374 this.refreshPeriod = refrehsPeriod; 375 this.cronExpression = cronExpression; 376 } 377 378 void setRefreshPeriod(Object value) { 379 try { 380 refreshPeriod = Integer.parseInt(value.toString()); 381 } 382 catch (NumberFormatException e) { 383 } 385 } 386 } 387 388 final class OSCacheAdministrator extends GeneralCacheAdministrator { 389 390 OSCacheAdministrator() { 391 } 392 393 OSCacheAdministrator(Properties properties) { 394 super(properties); 395 } 396 397 Properties getProperties() { 398 return super.config.getProperties(); 399 } 400 } 401 } 402 | Popular Tags |