001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (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 *     Gagnavarslan ehf
016 */
017package org.nuxeo.ecm.webdav.backend;
018
019import java.util.HashMap;
020import java.util.Map;
021import java.util.concurrent.ConcurrentHashMap;
022
023import org.nuxeo.ecm.core.api.CoreSession;
024import org.nuxeo.ecm.core.api.DocumentModel;
025import org.nuxeo.ecm.core.api.DocumentNotFoundException;
026import org.nuxeo.ecm.core.api.IdRef;
027
028public class PathCache {
029
030    private static final long FOLDER_LIFE_TIME = 30 * 60 * 1000;
031
032    private static final long FILE_LIFE_TIME = 1 * 60 * 1000;
033
034    private int maxSize;
035
036    private Map<String, Value> pathToUuidCache = new ConcurrentHashMap<String, Value>();
037
038    private CoreSession session;
039
040    public PathCache(CoreSession session, int maxSize) {
041        this.session = session;
042        this.maxSize = maxSize;
043    }
044
045    public void put(String path, DocumentModel model) {
046        if (model == null) {
047            return;
048        }
049        if (pathToUuidCache.size() >= maxSize) {
050            clean();
051        }
052        pathToUuidCache.put(path, new Value(System.currentTimeMillis()
053                + (model.isFolder() ? FOLDER_LIFE_TIME : FILE_LIFE_TIME), model.getId()));
054    }
055
056    public DocumentModel get(String path) {
057        Value value = pathToUuidCache.get(path);
058        if (value == null) {
059            return null;
060        }
061
062        if (value.getExpiredTime() < System.currentTimeMillis()) {
063            pathToUuidCache.remove(path);
064            return null;
065        }
066        String uuid = value.getValue();
067        DocumentModel model = null;
068        try {
069            model = session.getDocument(new IdRef(uuid));
070        } catch (DocumentNotFoundException e) {
071            // do nothing
072        }
073        if (model == null) {
074            pathToUuidCache.remove(path);
075        }
076
077        return model;
078    }
079
080    public void remove(String path) {
081        Map<String, Value> cacheCopy = new HashMap<String, Value>(pathToUuidCache);
082        for (String key : cacheCopy.keySet()) {
083            if (key.startsWith(path)) {
084                pathToUuidCache.remove(key);
085            }
086        }
087    }
088
089    private int clean() {
090        Map<String, Value> tmpMap = new HashMap<String, Value>(pathToUuidCache);
091        for (String key : tmpMap.keySet()) {
092            if ((pathToUuidCache.get(key).getExpiredTime()) < System.currentTimeMillis()) {
093                remove(key);
094            }
095        }
096        return pathToUuidCache.size();
097    }
098
099    private class Value {
100        private long expiredTime;
101
102        private String value;
103
104        private Value(long expiredTime, String value) {
105            this.expiredTime = expiredTime;
106            this.value = value;
107        }
108
109        public long getExpiredTime() {
110            return expiredTime;
111        }
112
113        @SuppressWarnings("unused")
114        public void setExpiredTime(long expiredTime) {
115            this.expiredTime = expiredTime;
116        }
117
118        public String getValue() {
119            return value;
120        }
121
122        @SuppressWarnings("unused")
123        public void setValue(String value) {
124            this.value = value;
125        }
126    }
127
128}