001/*
002 *  Copyright 2017 Anyware Services
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 */
016package org.ametys.plugins.workspaces.project.notification;
017
018import java.util.HashMap;
019import java.util.LinkedList;
020import java.util.Map;
021
022import org.apache.avalon.framework.activity.Initializable;
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027
028import org.ametys.core.user.CurrentUserProvider;
029
030/**
031 * Notification helper for the Webdav actions
032 */
033public class ResourceNotifierHelper implements Serviceable, Component, Initializable
034{
035    /** Avalon role. */
036    public static final String ROLE = ResourceNotifierHelper.class.getName();
037    
038    /** Time of expiration of a log (5 minutes) */
039    private static final long __HISTORY_EXPIRATION_TIME = 5 * 60 * 1000; 
040    /** Time duration between 2 cleansing of logs queue (10 seconds) */
041    private static final long __TIME_DURATION_BEFORE_NEXT_CLEAN = 10 * 1000; 
042    
043    /** The current user provider */
044    protected CurrentUserProvider _currentUserProvider;
045    
046    private LinkedList<Map<String, Object>> _sentHistory;
047    
048    private long _lastCleanTime;
049    
050    public void service(ServiceManager manager) throws ServiceException
051    {
052        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
053    }
054
055    public void initialize() throws Exception
056    {
057        _sentHistory = new LinkedList<>();
058    }
059    
060    /**
061     * Notify the observation manager when a resource is updated
062     * @param resourceId The resource updated
063     * @return True if the resource was recently modified
064     */
065    public boolean resourceRecentlyModified(String resourceId)
066    {
067        if (resourceId == null)
068        {
069            return false;
070        }
071        
072        long now = System.currentTimeMillis();
073        synchronized (_sentHistory)
074        {
075            _cleanupHistory();
076        
077            for (Map<String, Object> map : _sentHistory)
078            {
079                if (map.get("resourceId").equals(resourceId))
080                {
081                    return true;
082                }
083            }
084            
085            Map<String, Object> history = new HashMap<>();
086            history.put("time", now);
087            history.put("resourceId", resourceId);
088            _sentHistory.addLast(history);
089        }
090        
091        return false;
092    }
093
094    private void _cleanupHistory()
095    {
096        if (_lastCleanTime != 0 && _lastCleanTime + __TIME_DURATION_BEFORE_NEXT_CLEAN > System.currentTimeMillis())
097        {
098            // The time between 2 cleansing has not yet expired, do nothing
099            return;
100        }
101
102        long from = System.currentTimeMillis() - __HISTORY_EXPIRATION_TIME;
103        // Remove history before 'from'
104        Map<String, Object> oldHistory = _sentHistory.peek();
105        while (oldHistory != null && (long) oldHistory.get("time") < from)
106        {
107            _sentHistory.remove();
108            oldHistory = _sentHistory.peek();
109        }
110        
111        _lastCleanTime = System.currentTimeMillis();
112    }
113
114
115}