001/*
002 * (C) Copyright 2006-2009 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.ui.web.cache;
023
024import java.io.Serializable;
025import java.util.Calendar;
026import java.util.Map;
027import java.util.concurrent.locks.ReentrantReadWriteLock;
028
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentRef;
031
032public class ThreadSafeCacheHolder<T extends Serializable> implements Serializable {
033
034    public static final int DEFAULT_SIZE = 20;
035
036    private static final long serialVersionUID = 1L;
037
038    protected final Map<String, T> cacheMap;
039
040    protected final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
041
042    public ThreadSafeCacheHolder() {
043        this(DEFAULT_SIZE);
044    }
045
046    public ThreadSafeCacheHolder(int maxSize) {
047        cacheMap = new LRUCachingMap<String, T>(maxSize);
048    }
049
050    protected String getKey(DocumentRef docRef, String key) {
051        if (docRef == null) {
052            if (key == null) {
053                return "default";
054            } else {
055                return key;
056            }
057        } else {
058            if (key == null) {
059                return docRef.toString();
060            } else {
061                return docRef.toString() + "-" + key;
062            }
063        }
064    }
065
066    protected String getKey(DocumentModel doc, String key) {
067        DocumentRef docRef = doc.getRef();
068        Calendar modified = (Calendar) doc.getProperty("dublincore", "modified");
069        if (key == null) {
070            if (modified != null) {
071                key = modified.toString();
072            }
073        } else {
074            key = key + "-" + key;
075        }
076
077        return getKey(docRef, key);
078    }
079
080    // Adders
081    protected void doAdd(String key, T value) {
082        try {
083            cacheLock.writeLock().lock();
084            cacheMap.put(key, value);
085        } finally {
086            cacheLock.writeLock().unlock();
087        }
088    }
089
090    public void addToCache(String key, T value) {
091        doAdd(key, value);
092    }
093
094    public void addToCache(DocumentRef docRef, String key, T value) {
095        doAdd(getKey(docRef, key), value);
096    }
097
098    public void addToCache(DocumentModel doc, String key, T value) {
099        doAdd(getKey(doc, key), value);
100    }
101
102    // Getters
103    protected T doGet(String key) {
104        try {
105            cacheLock.readLock().lock();
106            return cacheMap.get(key);
107        } finally {
108            cacheLock.readLock().unlock();
109        }
110    }
111
112    public T getFromCache(String key) {
113        return doGet(key);
114    }
115
116    public T getFromCache(DocumentRef docRef, String key) {
117        return doGet(getKey(docRef, key));
118    }
119
120    public T getFromCache(DocumentModel doc, String key) {
121        return doGet(getKey(doc, key));
122    }
123
124    // Removers
125    protected void doRemove(String key) {
126        try {
127            cacheLock.writeLock().lock();
128            cacheMap.remove(key);
129        } finally {
130            cacheLock.writeLock().unlock();
131        }
132    }
133
134    public void removeFromCache(DocumentRef docRef, String key) {
135        doRemove(getKey(docRef, key));
136    }
137
138    public void removeFromCache(DocumentModel doc, String key) {
139        doRemove(getKey(doc, key));
140    }
141
142    public void removeFromCache(String key) {
143        doRemove(key);
144    }
145
146}