001/*
002 *  Copyright 2020 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 */
016
017package org.ametys.plugins.workspaces.documents.onlyoffice;
018
019import java.text.SimpleDateFormat;
020import java.util.Date;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028
029import org.ametys.core.ui.Callable;
030import org.ametys.runtime.plugin.component.AbstractLogEnabled;
031
032/**
033 * Manager for key/token used in OnlyOffice
034 */
035public class OnlyOfficeKeyManager extends AbstractLogEnabled implements Component, Serviceable
036{
037    /** The Avalon role */
038    public static final String ROLE = OnlyOfficeKeyManager.class.getName();
039    
040    private Map<String, KeyInformation> _onlyOfficeKeyStorage;
041    
042    @Override
043    public void service(ServiceManager manager) throws ServiceException
044    {
045        _onlyOfficeKeyStorage = new HashMap<>();
046    }
047    
048    private static class KeyInformation
049    {
050        private String _key;
051        private int _nbHolders = 1;
052        
053        KeyInformation(String key)
054        {
055            _key = key;
056        }
057        
058        synchronized void incrementHolders()
059        {
060            _nbHolders++;
061        }
062        
063        synchronized void decrementHolders()
064        {
065            _nbHolders--;
066        }
067    }
068    
069    /**
070     * getKey method
071     * If a key exist for the resourceId, return it and increment _nbHolders
072     * If no key exist for the resourceId, create a new key, put at 1 the _nbHolders and return the key
073     * @param resourceId id of the resource to look
074     * @return an onlyOfficeKey
075     */
076    @Callable
077    public synchronized Map<String, Object> getKey(String resourceId)
078    {
079        String tokenKey = _resourceIdToTokenKey(resourceId);
080        Map<String, Object> result = new HashMap<>();
081        String response;
082        
083        if (_onlyOfficeKeyStorage.containsKey(tokenKey))
084        {
085            KeyInformation keyInformation = _onlyOfficeKeyStorage.get(tokenKey);
086            keyInformation.incrementHolders();
087            response = keyInformation._key;
088        }
089        else
090        {
091            KeyInformation keyInformation = create(tokenKey);
092            response = keyInformation._key;
093        }
094        
095        result.put("keyReponse", response);
096        
097        return result;
098    }
099    
100    /**
101     * create method
102     * @param tokenKey id of the resource associate to the new key
103     * @return the new key
104     */
105    protected KeyInformation create(String tokenKey)
106    {
107        String currentTime = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
108        String key = tokenKey + "." + currentTime;
109        KeyInformation keyInformation = new KeyInformation(key);
110        _onlyOfficeKeyStorage.put(tokenKey, keyInformation);
111        
112        return keyInformation;
113    }
114    
115    /**
116     * remove method
117     * @param resourceId id of the resource
118     * @param removeAll Force to remove all keys
119     * @return map with error or success
120     */
121    @Callable
122    public Map<String, Object> remove(String resourceId, boolean removeAll)
123    {
124        String tokenKey = _resourceIdToTokenKey(resourceId);
125        Map<String, Object> result = new HashMap<>();
126        
127        if (_onlyOfficeKeyStorage.containsKey(tokenKey))
128        {
129            KeyInformation keyInformation = _onlyOfficeKeyStorage.get(tokenKey);
130            
131
132            if (removeAll || keyInformation._nbHolders < 2)
133            {
134                _onlyOfficeKeyStorage.remove(tokenKey);
135                result.put("success", "keyDeleted");
136            }
137            else
138            {
139                keyInformation.decrementHolders();
140                result.put("success", "nbUserDecremented");
141            }
142        }
143        else
144        {
145            result.put("error", "unknownKey");
146        }
147        return result;
148    }
149    
150    private String _resourceIdToTokenKey(String ressourceId)
151    {
152        int index = ressourceId.lastIndexOf("//") + 2;
153        
154        return ressourceId.substring(index);
155    }
156}