001/* 002 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.cache; 021 022import java.io.Serializable; 023import java.util.Calendar; 024import java.util.Map; 025import java.util.concurrent.locks.ReentrantReadWriteLock; 026 027import org.nuxeo.ecm.core.api.DocumentModel; 028import org.nuxeo.ecm.core.api.DocumentRef; 029 030public class ThreadSafeCacheHolder<T extends Serializable> implements Serializable { 031 032 public static final int DEFAULT_SIZE = 20; 033 034 private static final long serialVersionUID = 1L; 035 036 protected final Map<String, T> cacheMap; 037 038 protected final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); 039 040 public ThreadSafeCacheHolder() { 041 this(DEFAULT_SIZE); 042 } 043 044 public ThreadSafeCacheHolder(int maxSize) { 045 cacheMap = new LRUCachingMap<String, T>(maxSize); 046 } 047 048 protected String getKey(DocumentRef docRef, String key) { 049 if (docRef == null) { 050 if (key == null) { 051 return "default"; 052 } else { 053 return key; 054 } 055 } else { 056 if (key == null) { 057 return docRef.toString(); 058 } else { 059 return docRef.toString() + "-" + key; 060 } 061 } 062 } 063 064 protected String getKey(DocumentModel doc, String key) { 065 DocumentRef docRef = doc.getRef(); 066 Calendar modified = (Calendar) doc.getProperty("dublincore", "modified"); 067 if (key == null) { 068 if (modified != null) { 069 key = modified.toString(); 070 } 071 } else { 072 key = key + "-" + key; 073 } 074 075 return getKey(docRef, key); 076 } 077 078 // Adders 079 protected void doAdd(String key, T value) { 080 try { 081 cacheLock.writeLock().lock(); 082 cacheMap.put(key, value); 083 } finally { 084 cacheLock.writeLock().unlock(); 085 } 086 } 087 088 public void addToCache(String key, T value) { 089 doAdd(key, value); 090 } 091 092 public void addToCache(DocumentRef docRef, String key, T value) { 093 doAdd(getKey(docRef, key), value); 094 } 095 096 public void addToCache(DocumentModel doc, String key, T value) { 097 doAdd(getKey(doc, key), value); 098 } 099 100 // Getters 101 protected T doGet(String key) { 102 try { 103 cacheLock.readLock().lock(); 104 return cacheMap.get(key); 105 } finally { 106 cacheLock.readLock().unlock(); 107 } 108 } 109 110 public T getFromCache(String key) { 111 return doGet(key); 112 } 113 114 public T getFromCache(DocumentRef docRef, String key) { 115 return doGet(getKey(docRef, key)); 116 } 117 118 public T getFromCache(DocumentModel doc, String key) { 119 return doGet(getKey(doc, key)); 120 } 121 122 // Removers 123 protected void doRemove(String key) { 124 try { 125 cacheLock.writeLock().lock(); 126 cacheMap.remove(key); 127 } finally { 128 cacheLock.writeLock().unlock(); 129 } 130 } 131 132 public void removeFromCache(DocumentRef docRef, String key) { 133 doRemove(getKey(docRef, key)); 134 } 135 136 public void removeFromCache(DocumentModel doc, String key) { 137 doRemove(getKey(doc, key)); 138 } 139 140 public void removeFromCache(String key) { 141 doRemove(key); 142 } 143 144}