package org.maachang.proxy.engine.admin;

import java.util.HashMap;

import org.maachang.util.RandomUtil;

/**
 * MaachangProxy管理セッション.
 * 
 * @version 2008/03/26
 * @author masahito suzuki
 * @since MaachangProxy 1.00
 */
public class AdminSession {
    private static final int SIZE = 64 ;
    private AdminSessionThread thread = null ;
    private HashMap<String,Long> session = null ;
    
    public AdminSession() throws Exception {
        session = new HashMap<String,Long>() ;
        thread = new AdminSessionThread( this ) ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    public synchronized void destroy() {
        if( thread != null ) {
            thread.destroy() ;
        }
        thread = null ;
        session = null ;
    }
    
    public synchronized String createSession()
        throws Exception {
        String key = null ;
        for( ;; ) {
            key = RandomUtil.randomString( SIZE,true,true,true ) ;
            if( session.get( key ) == null ) {
                session.put( key,new Long( System.currentTimeMillis() ) ) ;
                break ;
            }
            Thread.sleep( 50L ) ;
        }
        return key ;
    }
    
    public synchronized boolean updateSession( String key ) {
        Long data = session.get( key ) ;
        if( data == null ) {
            return false ;
        }
        session.put( key,new Long( System.currentTimeMillis() ) ) ;
        return true ;
    }
    
    public synchronized Long getSession( String key ) {
        return session.get( key ) ;
    }
    
    public synchronized void removeSession( String key ) {
        session.remove( key ) ;
    }
    
    protected synchronized Object[] getKey() {
        return session.keySet().toArray() ;
    }
    
}

class AdminSessionThread extends Thread {
    private static final long TIME_OUT = 30L*60L*1000L ;
    private AdminSession session = null ;
    private volatile boolean stopFlag = true ;
    
    private AdminSessionThread() {
        
    }
    
    public AdminSessionThread( AdminSession session )
        throws Exception {
        this.session = session ;
        this.stopFlag = false ;
        this.setDaemon( true ) ;
        this.start() ;
    }
    
    public void destroy() {
        setStop( true ) ;
    }
    
    public synchronized boolean isStop() {
        return stopFlag ;
    }
    
    private synchronized void setStop( boolean mode ) {
        this.stopFlag = mode ;
    }
    
    public void run() {
        boolean endFlag = false ;
        ThreadDeath threadDeach = null ;
        for( ;; ) {
            if( endFlag == true || isStop() == true ) {
                break ;
            }
            try {
                Object[] keys = session.getKey() ;
                if( keys != null && keys.length > 0 ) {
                    int len = keys.length ;
                    for( int i = 0 ; i < len ; i ++ ) {
                        Thread.sleep( 50L ) ;
                        String key = ( String )keys[ i ] ;
                        if( key == null ) {
                            session.removeSession( key ) ;
                        }
                        else {
                            Long data = session.getSession( key ) ;
                            if( data == null || data.longValue() + TIME_OUT <= System.currentTimeMillis() ) {
                                session.removeSession( key ) ;
                            }
                        }
                    }
                }
                Thread.sleep( 1000L ) ;
            } catch( InterruptedException ite ) {
                endFlag = true ;
            } catch ( NullPointerException ne ) {
            } catch( OutOfMemoryError mem ) {
            } catch( Exception e ) {
            } catch( ThreadDeath td ) {
                endFlag = true ;
                threadDeach = td ;
            }
        }
        this.session = null ;
        setStop( true ) ;
        if( threadDeach != null ) {
            throw threadDeach ;
        }
    }
    
}


