All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jradius.session.JRadiusSessionManager Maven / Gradle / Ivy

The newest version!
/**
 * JRadius - A RADIUS Server Java Adapter
 * Copyright (C) 2004-2006 PicoPoint, B.V.
 * Copyright (c) 2007 David Bird 
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

package net.jradius.session;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;

import net.jradius.exception.RadiusException;
import net.jradius.log.JRadiusLogEntry;
import net.jradius.log.RadiusLog;
import net.jradius.server.EventDispatcher;
import net.jradius.server.JRadiusEvent;
import net.jradius.server.JRadiusRequest;
import net.jradius.server.event.SessionExpiredEvent;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
import net.sf.ehcache.event.CacheEventListener;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class JRadiusSessionManager implements InitializingBean, ApplicationContextAware, CacheEventListener
{
    private static JRadiusSessionManager defaultManager;

    private static HashMap managers = new HashMap();

    private HashMap providers = new HashMap();
    private HashMap factories = new HashMap();

    private ApplicationContext applicationContext;

    private int minInterimInterval  = 300;
    private int maxInactiveInterval = 2100;

    private String cacheName = "jradius-session";
    private String logCacheName = "jradius-log";
    

    private CacheManager cacheManager;
    private Cache sessionCache;
    private Cache logCache;

    private EventDispatcher eventDispatcher;

    /**
     * There is a single JRadiusSessionManager available that
     * is accessible through this method. Using the default
     * application-wide manager is sufficient for most uses.
     * For specific needs, it is possible to create a new
     * JRadiusSessionManager object.
     * @return the default JRadiusSessionManager instance
     */
    public static JRadiusSessionManager getManager(Object name)
    {
        JRadiusSessionManager manager = null;
     
        if (name != null)
        {
            manager = (JRadiusSessionManager) managers.get(name);
        }

        if (manager == null) 
        {
            if (defaultManager == null)
            {
                defaultManager = new JRadiusSessionManager();
                try
                {
                    defaultManager.afterPropertiesSet();
                }
                catch (Exception e)
                {
                    RadiusLog.error("Error in JRadius Session Manager", e);
                }
            }
         
            manager = defaultManager;
        }
        
        return manager;
    }

    public static JRadiusSessionManager setManager(String name, JRadiusSessionManager manager)
    {
        if (name != null)
        {
            managers.put(name, manager);
        }
        else
        {
            defaultManager = manager;
        }

        return manager;
    }

    public static void shutdownManagers() 
    {
        if (defaultManager != null)
        {
            defaultManager.shutdown();
        }
        
        for (Iterator i = managers.values().iterator(); i.hasNext();)
        {
            JRadiusSessionManager manager = (JRadiusSessionManager)i.next();
            manager.shutdown();
        }
    }
    
    /**
     * Creates a new JRadiusSessionManager instance. This
     * sets the key provider and session factory to the
     * DefaultSessionKeyProvider and RadiusSessionFactory,
     * respectively
     */
    public JRadiusSessionManager()
    {
        initialize();
    }
    
    private void initialize()
    {
        try
        {
            // If we can find the extended JRadius classes, configure
            // the default RadiusSessionKeyProvider and RadiusSessionFactory
            Class c;
            c = Class.forName("net.jradius.session.RadiusSessionKeyProvider");
            providers.put(null, (SessionKeyProvider) c.newInstance());
            c = Class.forName("net.jradius.session.RadiusSessionFactory");
            factories.put(null, (SessionFactory) c.newInstance());
        }
        catch (Exception e)
        {
            RadiusLog.error("Could not find extended JRadius classes - not running JRadiusSessionManager", e);
            throw new RuntimeException(e);
        }
    }

    public void shutdown()
    {
    	if (cacheManager != null && cacheManager.getStatus() == Status.STATUS_ALIVE)
        {
            cacheManager.shutdown();
        }
    }
    
    public void afterPropertiesSet() throws Exception
    {
    	if ((sessionCache == null || logCache == null) && cacheManager == null) 
        {
        	throw new RuntimeException("cacheManager required");
        }

        if (sessionCache == null) 
        {
            sessionCache = cacheManager.getCache(cacheName);

            if (sessionCache == null)
            {
            	sessionCache = new Cache(cacheName, 1000, true, false, maxInactiveInterval, maxInactiveInterval);
                cacheManager.addCache(sessionCache);
            }
        }

        if (logCache == null) 
        {
            logCache = cacheManager.getCache(logCacheName);

            if (logCache == null)
            {
            	logCache = new Cache(logCacheName, 100, true, false, maxInactiveInterval, maxInactiveInterval);
                cacheManager.addCache(logCache);
            }
        }

        sessionCache.getCacheEventNotificationService().registerListener(this);
        logCache.getCacheEventNotificationService().registerListener(this);
    }

    /**
     * Sets the key provider for this session manager. The
     * key provider generates a key to store a session with.
     * The key is generated based on a JRadiusRequest that is
     * passed to the key provider's getSessionKey method.
     * Keys are used to retrieve stored sessions from the session
     * manager.
     * @param name The name of the SessionKeyProvider (null for default)
     * @param provider The SessionKeyProvider
     * @see SessionKeyProvider
     */
    public void setSessionKeyProvider(String name, SessionKeyProvider provider)
    {
        providers.put(name, provider);
    }
    
    /**
     * Sets the session factory for this session manager. The
     * session factory generates a new session object, possibly
     * initialized based on values of a JRadiusRequest.
     * @param name The name of the SessionFactory (null for default)
     * @param factory a SessionFactory
     * @see SessionFactory
     */
    public void setSessionFactory(String name, SessionFactory factory)
    {
        factories.put(name, factory);
    }
    
    /**
     * returns the session manager's key provider
     * @param name The name of the SessionKeyProvider (null for default)
     * @return the session manager's key provider
     */
    public SessionKeyProvider getSessionKeyProvider(Object name)
    {
        SessionKeyProvider provider = (SessionKeyProvider)providers.get(name);
        if (provider == null && name != null) provider = (SessionKeyProvider)providers.get(null);
        return provider;
    }
    
    /**
     * returns the session manager's session factory
     * @param name The name of the SessionFactory (null for default)
     * @return the session manager's session factory
     */
    public SessionFactory getSessionFactory(Object name)
    {
        SessionFactory factory = (SessionFactory)factories.get(name);
        if (factory == null && name != null) factory = (SessionFactory)factories.get(null);
        return factory;
    }
    
    /**
     * Returns a session object. First, a key is generated by
     * the session manager's key provider, based on the JRadiusRequest.
     * If there is a stored session based on the key, this session is
     * returned, otherwise a new session created by the session factory
     * is returned
     * @param request a JRadiusRequest used to retrieve or generate a session with
     * @return Returns a RadiusSession
     * @throws RadiusException
     */
    public JRadiusSession getSession(JRadiusRequest request) throws RadiusException
    {
        SessionKeyProvider skp = getSessionKeyProvider(request.getSender());
        Serializable key = skp.getAppSessionKey(request);
        JRadiusSession session = null;
        Serializable nkey = null;
        
        if (key != null) 
        {
            RadiusLog.debug("** Looking for session: " + key);
            
            session = getSession(request, key);
            if (session == null)
            {
                RadiusLog.error("Broken JRadius-Session-Id implementation for session: " + key);
                key = null;
            }
        }

        if (key == null)
        {
            key = skp.getClassKey(request);
            
            if (key != null) 
            {
                RadiusLog.debug("** Looking for session: " + key);
                
                session = getSession(request, key);
                if (session == null)
                {
                    RadiusLog.error("Broken Class implementation for session: " + key);
                    key = null;
                }
                else
                {
                    if (session.getJRadiusKey() != null && !session.getJRadiusKey().equals(session.getSessionKey()))
                    {
                        rehashSession(session, session.getJRadiusKey(), key);
                    }
                }
            }
        }

        if (key == null)
        {
            Serializable keys = skp.getRequestSessionKey(request);
        
            if (keys == null)
            {
                return null;
            }
        
            if (keys instanceof Serializable[])
            {
                key = ((Serializable[])(keys))[0];
                nkey = ((Serializable[])(keys))[1];
                RadiusLog.debug("Rehashing session with key " + key + " under new key " + nkey);
            }
            else
            {
                key = keys;
            }
            
            RadiusLog.debug("** Looking for session: " + key);
            session = getSession(request, key);

            if (session != null && nkey != null && !nkey.equals(key))
            {
                rehashSession(session, key, nkey);
            }
        }        

        if (session == null) 
        {
            session = newSession(request, nkey == null ? key : nkey);
        }
        
        session.setTimeStamp(System.currentTimeMillis());
        //session.setLastRadiusRequest(request);
        
        return session;
    }

    public void rehashSession(JRadiusSession session, Serializable okey, Serializable nkey) throws RadiusException
    {
        remove(okey);
        session.setJRadiusKey((String)nkey);
        put(session.getJRadiusKey(), session);
    }

    public JRadiusSession newSession(JRadiusRequest request, Object key) throws RadiusException
    {
        JRadiusSession session = (JRadiusSession) getSessionFactory(request.getSender()).newSession(request);
        session.setJRadiusKey((String)key);
        put(session.getJRadiusKey(), session);
        put(session.getSessionKey(), session);
        return session;
    }

    public JRadiusSession getSession(JRadiusRequest request, Serializable key) throws RadiusException
    {
        Element element = sessionCache.get(key);
        JRadiusSession session = null;

        if (element != null)
        {
        	session = (JRadiusSession) element.getValue();
        }
        
        if (session == null && request != null)
        {
            SessionFactory sf = getSessionFactory(request.getSender());
            session = sf.getSession(request, key);
            if (session != null)
            {
                put(session.getJRadiusKey(), session);
                put(session.getSessionKey(), session);
            }
        }
        
        if (session == null) return null;
        
        return session;
    }

    public void lock(JRadiusSession session)
    {
        session.lock();
        //RadiusLog.error("Appropriate session locking must be implemented");
    }

    public void unlock(JRadiusSession session, boolean save)
    {
        session.unlock();
        //RadiusLog.error("Appropriate session locking must be implemented");
    }

    public JRadiusLogEntry newLogEntry(JRadiusEvent event, JRadiusSession session, String packetId) 
    {
        Object sender = null;
        
        if (event != null) 
            sender = event.getSender();
        
//        else if (session != null && session.getLastRadiusRequest() != null) 
//            sender = session.getLastRadiusRequest().getSender();
        
        return getSessionFactory(sender).newSessionLogEntry(event, session, packetId);
    }
    
    public void removeSession(JRadiusSession session) 
    {
        if (session != null)
        {
            remove(session.getJRadiusKey());
            remove(session.getSessionKey());
        }
    }
    
    private void remove(Serializable key)
    {
    	RadiusLog.debug("Removing session key: " + key);
        sessionCache.remove(key);
    }

    private void put(Object key, Object value)
    {
        RadiusLog.debug("Adding session key: " + key);
        sessionCache.put(new Element(key, value));
    }

    public int getMaxInactiveInterval()
    {
        return maxInactiveInterval;
    }

    public void setMaxInactiveInterval(int maxInactiveInterval)
    {
        this.maxInactiveInterval = maxInactiveInterval;
    }

    public int getMinInterimInterval()
    {
        return minInterimInterval;
    }

    public void setMinInterimInterval(int minInterimInterval)
    {
        this.minInterimInterval = minInterimInterval;
    }
    
    public CacheManager getCacheManager()
    {
        return cacheManager;
    }

    public void setCacheManager(CacheManager cacheManager)
    {
        this.cacheManager = cacheManager;
    }

    public String getCacheName()
    {
        return cacheName;
    }

    public void setCacheName(String cacheName)
    {
        this.cacheName = cacheName;
    }

    public void dispose()
    {
    }

    public void notifyElementEvicted(Ehcache cache, Element element)
    {
    }

    public void notifyElementExpired(Ehcache cache, Element element)
    {
        Object value = element.getValue();
        if (value != null && value instanceof JRadiusSession)
        {
            JRadiusSession session = (JRadiusSession) value;
            RadiusLog.debug("Expired session: " + session.getSessionKey());
            if (eventDispatcher != null)
            {
                SessionExpiredEvent evt = new SessionExpiredEvent(session);
                evt.setApplicationContext(applicationContext);
                eventDispatcher.post(evt);
            }
        }
    }

    public void notifyElementPut(Ehcache cache, Element element) throws CacheException
    {
    }

    public void notifyElementRemoved(Ehcache cache, Element element) throws CacheException
    {
    }

    public void notifyElementUpdated(Ehcache cache, Element element) throws CacheException
    {
    }

    public void notifyRemoveAll(Ehcache cache)
    {
    }

    public Object clone() throws CloneNotSupportedException
    {
    	throw new CloneNotSupportedException();
    }

    public Ehcache getSessionCache()
    {
        return sessionCache;
    }

    public void setSessionCache(Cache sessionCache)
    {
        this.sessionCache = sessionCache;
    }

    public void setEventDispatcher(EventDispatcher eventDispatcher)
    {
		this.eventDispatcher = eventDispatcher;
	}

	public ApplicationContext getApplicationContext()
    {
        return applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext)
    {
        this.applicationContext = applicationContext;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy