org.glite.slcs.session.impl.MemorySessions.java Source code

Java tutorial

Introduction

Here is the source code for org.glite.slcs.session.impl.MemorySessions.java

Source

/*
 * $Id: MemorySessions.java,v 1.7 2008/07/21 08:10:28 vtschopp Exp $
 *
 * Copyright (c) Members of the EGEE Collaboration. 2004.
 * See http://eu-egee.org/partners/ for details on the copyright holders.
 * For license conditions see the license file or http://eu-egee.org/license.html 
 */
package org.glite.slcs.session.impl;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.glite.slcs.config.SLCSServerConfiguration;
import org.glite.slcs.session.SLCSSession;
import org.glite.slcs.session.SLCSSessions;
import org.glite.slcs.util.Utils;

/**
 * MemorySessions is the memory implementation of the SLCSSessions. Uses a
 * cleaning task to delete expired sessions.
 * 
 * @author Valery Tschopp <tschopp@switch.ch>
 * @version $Revision: 1.7 $
 */
public class MemorySessions implements SLCSSessions {

    /** logging */
    public static Log LOG = LogFactory.getLog(MemorySessions.class);

    /** Date format for toString */
    static private SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

    /** hashtable to store the (token,SessionEntry) pair */
    private Hashtable sessions_ = null;

    private Object sessionsMutex_ = new Object();

    /** random bytes generator */
    private SecureRandom random_ = null;

    /** memory sessions cleaning thread */
    private MemorySessionsCleaner memorySessionsCleaner_ = null;

    /** default TTL: 300 seconds */
    private long sessionTTL_ = 300;

    /**
     * Constructor accessed only by factory
     */
    public MemorySessions() {
        super();
        sessions_ = new Hashtable();
        try {
            random_ = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException e) {
            LOG.error(e);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glite.slcs.session.SLCSSessions#init()
     */
    public void init(SLCSServerConfiguration config) {
        // read SessionTTL from config
        if (config.contains(SLCSServerConfiguration.COMPONENTSCONFIGURATION_PREFIX + ".SLCSSessions.SessionTTL")) {
            int sessionTTL = config
                    .getInt(SLCSServerConfiguration.COMPONENTSCONFIGURATION_PREFIX + ".SLCSSessions.SessionTTL");
            this.sessionTTL_ = sessionTTL;
        }
        LOG.info("SLCSSessions.SessionTTL=" + sessionTTL_);

        // read CleaningInterval (in seconds) for the memory cleaner thread
        int cleaningInterval = 60; // default 1 minute
        if (config.contains(
                SLCSServerConfiguration.COMPONENTSCONFIGURATION_PREFIX + ".SLCSSessions.CleaningInterval")) {
            cleaningInterval = config.getInt(
                    SLCSServerConfiguration.COMPONENTSCONFIGURATION_PREFIX + ".SLCSSessions.CleaningInterval");
        }
        LOG.info("SLCSSessions.CleaningInterval=" + cleaningInterval);
        // and create/start the cleaning thread
        memorySessionsCleaner_ = new MemorySessionsCleaner(cleaningInterval);
        memorySessionsCleaner_.start();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glite.slcs.SLCSServerComponent#shutdown()
     */
    public void shutdown() {
        // stop the cleaning thread
        if (memorySessionsCleaner_ != null) {
            LOG.info("shutdown the MemorySessionsCleaner");
            memorySessionsCleaner_.shutdown();
            memorySessionsCleaner_ = null;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glite.slcs.session.SLCSSessions#createSession(java.lang.String)
     */
    public SLCSSession createSession(String dn) {
        // create a random token
        String token = createRandomToken();
        // store the pair
        SLCSSession session = new SessionEntry(token, dn, sessionTTL_);
        if (LOG.isDebugEnabled()) {
            LOG.debug("add: " + session);
        }
        synchronized (sessionsMutex_) {
            sessions_.put(token, session);
        }
        // return the session
        return session;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glite.slcs.session.SLCSSessions#deleteToken(java.lang.String)
     */
    public void removeSession(String token) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("remove: " + token);
        }
        synchronized (sessionsMutex_) {
            sessions_.remove(token);
        }
    }

    /**
     * Returns the SessionEntry for this token.
     * 
     * @param token
     *            The session token (id)
     * @return The session or <code>null</code> if the session doesn't exists.
     */
    private SessionEntry getSessionEntry(String token) {
        if (sessions_.containsKey(token)) {
            SessionEntry session = (SessionEntry) sessions_.get(token);
            return session;
        }
        return null;
    }

    /**
     * Returns the session if and only if the token-dn pair exists in the
     * sessions.
     * 
     * @param token
     *            The session token.
     * @param dn
     *            The subject DN.
     * @return The session or <code>null</code> if the session doesn't exists.
     */
    public SLCSSession getSession(String token, String dn) {
        SessionEntry session = getSessionEntry(token);
        if (session != null) {
            String storedDN = session.getDN();
            if (storedDN.equals(dn)) {
                return session;
            }
        }
        return null;
    }

    /**
     * @return A 64 chars random token
     */
    private String createRandomToken() {
        byte[] randomBytes = null;
        randomBytes = new byte[32];
        random_.nextBytes(randomBytes);
        String token = Utils.toHexString(randomBytes);
        return token;
    }

    /**
     * SessionEntry implements the SLCSSession interface.
     * 
     * @author Valery Tschopp <tschopp@switch.ch>
     * @version $Revision: 1.7 $
     */
    public class SessionEntry implements SLCSSession {

        /** Cerificate DN */
        private String dn_ = null;

        /** Authorisation token */
        private String token_ = null;

        /** Creation time (milis) */
        private long time_ = 0;

        /** Attributes list */
        private List attributes_ = null;

        /** TTL in millis */
        private long ttl_ = 0;

        /**
         * Constructor.
         * 
         * @param token
         *            The session token.
         * @param dn
         *            The session DN.
         * @param ttl
         *            The time to live in seconds
         */
        public SessionEntry(String token, String dn, long ttl) {
            this.dn_ = dn;
            this.token_ = token;
            this.time_ = System.currentTimeMillis();
            // convert seconds to millis
            this.ttl_ = ttl * 1000;
            // attributes store
            this.attributes_ = new ArrayList();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.glite.slcs.session.SLCSSession#getToken()
         */
        public String getToken() {
            return this.token_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.glite.slcs.session.SLCSSession#getDN()
         */
        public String getDN() {
            return this.dn_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.glite.slcs.session.SLCSSession#setAttributes(java.util.List)
         */
        public void setAttributes(List attributes) {
            attributes_ = attributes;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.glite.slcs.session.SLCSSession#getAttributes()
         */
        public List getAttributes() {
            return attributes_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.glite.slcs.session.SLCSSession#isValid()
         */
        public boolean isValid() {
            long currentTime = System.currentTimeMillis();
            long deathTime = time_ + ttl_;
            boolean valid = currentTime <= deathTime;
            return valid;
        }

        /**
         * @return <code>true</code> iff the session is expired.
         */
        public boolean isExpired() {
            return !isValid();
        }

        /*
         * (non-Javadoc)
         * 
         * @see java.lang.Object#toString()
         */
        public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append("Session[");
            sb.append(token_).append(':');
            sb.append(dn_).append(':');
            if (!attributes_.isEmpty()) {
                sb.append(attributes_).append(':');
            }
            long deathTime = time_ + ttl_;
            Date date = new Date(deathTime);
            sb.append(DATE_FORMATTER.format(date));
            sb.append(']');
            return sb.toString();
        }
    }

    /**
     * MemorySessionsCleaner is a cleaning task which removes the expired SLCS
     * sessions every given time interval.
     * 
     * @author Valery Tschopp <tschopp@switch.ch>
     * @version $Revision: 1.7 $
     */
    private class MemorySessionsCleaner extends Timer {

        private long cleaningInterval_ = 60 * 1000; // one minute

        /**
         * Creates a {@link MemorySessionsCleaner} object with default 60
         * seconds interval.
         */
        public MemorySessionsCleaner() {
            this(60);
        }

        /**
         * Creates a {@link MemorySessionsCleaner} object with the given
         * interval in seconds.
         * 
         * @param seconds
         *            The interval between to run.
         */
        public MemorySessionsCleaner(int seconds) {
            super(true); // daemon
            this.cleaningInterval_ = seconds * 1000;
        }

        public void start() {
            LOG.info("schedule the MemorySessionsCleaningTask (" + cleaningInterval_ + " ms)");
            scheduleAtFixedRate(new MemorySessionsCleaningTask(), 0, cleaningInterval_);
        }

        public void shutdown() {
            LOG.info("cancel the MemorySessionsCleaningTask");
            this.cancel();
        }

        /**
         * MemorySessionsCleaningTask scheduled by the MemorySessionsCleaner
         * every cleaningInterval to remove the expired SLCS sessions.
         */
        class MemorySessionsCleaningTask extends TimerTask {

            /**
             * Removes expired SLCSSessions.
             */
            public void run() {
                synchronized (sessionsMutex_) {
                    if (!sessions_.isEmpty()) {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("checking sessions: " + sessions_.size());
                        }
                        Enumeration sessionEntries = sessions_.elements();
                        while (sessionEntries.hasMoreElements()) {
                            SessionEntry session = (SessionEntry) sessionEntries.nextElement();
                            if (session.isExpired()) {
                                LOG.info("Removing expired session: " + session);
                                sessions_.remove(session.getToken());
                            }
                        }
                    }
                }
            }
        }

    }
}