/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/urm/org/apache/slide/urm/utils/validatorcache/URMValidatorCache.java,v 1.4 2005/03/02 10:53:36 eckehard Exp $
 * $Revision: 1.4 $
 * $Date: 2005/03/02 10:53:36 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.slide.urm.utils.validatorcache;
import org.apache.slide.urm.utils.validatorcache.URMValidatorFifoCache;
import java.util.Map;
import java.util.HashMap;
import org.apache.slide.urm.accesscontroler.URMPermissionResult;
import java.util.Iterator;
import java.util.List;

/**
 * @author eckehard.hermann@softwareag.com
 * @author dieter.kessler@softwareag.com
 * @author zsolt.sasvarie@softwareag.com
 */

public class URMValidatorCache
{
    private static URMValidatorCache cache = null;
    private URMValidatorFifoCache fifo = null;
    private int _subjectSize = 1000;
    private static final Object cacheSyncObj = new Object();
    /**
     * Returns the current URMValidatorCache instance
     *
     * @return URMValidatorCache, current validator cache
     */
    public static URMValidatorCache getCache()
    {
        synchronized (cacheSyncObj) {
            if (cache == null)
                cache = new URMValidatorCache();
        }
        return cache;
    }

    /**
     * Returns the current URMValidatorCache instance
     *
     * @return URMValidatorCache, current validator cache
     */
    public static URMValidatorCache getCacheForValidator(URMListener _listener)
    {
        synchronized (cacheSyncObj) {
            if (cache == null)
                cache = new URMValidatorCache(_listener);
        }
        return cache;
    }
    
    /**
     * Initializes the cache
     *
     * @param    uriSize      max. uri cache size
     * @param    subjectSize  max subject caches per uri
     *
     */
    public static void initCache(int uriSize, int subjectSize)
    {
        synchronized (cacheSyncObj) {
            if (cache != null) cache = new URMValidatorCache (uriSize, subjectSize);
        }
    }
    
    /**
     * Return true if cache has been initialized
     *
     * @return ,true if cache has been initialized
     *
     */
    public static boolean isCacheInitialized()
    {
        if (cache != null) return true;
        return false;
    }

    /**
     * Creates a new cache with the passed size
     *
     * @param    uriSize      max. uri cache size
     * @param    subjectSize  max subject caches per uri
     *
     */
    public URMValidatorCache (int uriSize, int subjectSize) {
        fifo = new URMValidatorFifoCache(uriSize);
        _subjectSize = subjectSize;
    }
    
    /**
     * Creates a new cache with the default size (10000)
     *
     *
     */
    public URMValidatorCache (URMListener listener) {
        fifo = new URMValidatorFifoCache(10000);
        listener = listener;
    }
    
    /**
     * Creates a new cache with the default size (10000)
     *
     *
     */
    public URMValidatorCache () {
        fifo = new URMValidatorFifoCache(10000);
    }
    
    /**
     * Removes all elements from the cache
     *
     * @return   a boolean, if successful
     *
     */
    public synchronized boolean reset()
    {
        return fifo.clear();
    }
    
    /**
     * Removes the uri from the cache
     *
     * @param    uri  of the elment that should be removed
     *
     * @return   value of removed element
     *
     */
    public synchronized Object remove(String uri)
    {
        return fifo.remove(uri);
    }
    
    /**
     * adds a new permission entry for the passed subject and uri to the cache
     *
     * @param resources that should be cached
     * @param subject uri for that the permission at the passes uri should be cached
     * @param action that has been checked
     * @param permission that should be cached
     */
    public synchronized void addPermission(List resources, String subject, String action, URMPermissionResult permission){
        String uri = null;
        Iterator resourceIter = resources.iterator();
        while (resourceIter.hasNext()) {
            if (uri == null) uri = (String) resourceIter.next();
            else uri = uri + "/" + (String) resourceIter.next();
        }
        
        URMValidatorFifoCache uriMap = (URMValidatorFifoCache) fifo.get(uri);
        if (uriMap == null) {
            uriMap = new URMValidatorFifoCache(_subjectSize);
            new URMListenerResource(uri,resources,URMListener.getAclListenerSet(this));
            fifo.add(uri, uriMap);
            Map subjectMap = new HashMap();
            uriMap.add(subject, subjectMap);
            subjectMap.put(action, permission);
        } else {
            Map subjectMap = (Map) uriMap.get(subject);
            if (subjectMap == null) {
                subjectMap = new HashMap();
                uriMap.add(subject, subjectMap);
                subjectMap.put(action, permission);
            } else {
                subjectMap.put(action,permission);
            }
        }
    }

    /**
     * checks a permission entry for the passed subject and uri
     *
     * @param uri for that the permission should be cached
     * @param subject uri for that the permission at the passes uri should be cached
     * @param action that should be checked
     */
    public synchronized URMPermissionResult checkPermission(String uri, String subject, String action){
        URMValidatorFifoCache uriMap = (URMValidatorFifoCache) fifo.get(uri);
        if (uriMap == null) return null;
        Map subjectMap = (Map) uriMap.get(subject);
        if (subjectMap == null) return null;
        return (URMPermissionResult) subjectMap.get(action);
    }
}

