/* $Id: SimpleSession.java,v 1.1 2007/10/29 02:55:37 nito Exp $
 *
 * Copyright (c)ARGO 21, Corporation. 2005, 2006.  All rights reserved.
 * 
 * This file is part of Nautica Workflow Core.
 * 
 *  Nautica Workflow Core 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.
 * 
 *  Nautica Workflow Core 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 Nautica Workflow Core; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
 */
package jp.co.argo21.nautica.workflow.security.simple;

import java.security.SecureRandom;
import java.util.Date;

import jp.co.argo21.nautica.workflow.omg.WorkflowException;
import jp.co.argo21.nautica.workflow.security.Session;
import jp.co.argo21.nautica.workflow.security.User;

/**
 * SimpleSessionは、SimpleSessionManager用のセッション情報を表すクラスである。
 *
 * @author  nito(Argo 21, Corp.)
 * @author  mmanabe(Argo 21, Corp.)
 * @version $Revision: 1.1 $
 * @since   Nautica Workflow 1.0
 */
public class SimpleSession implements Session {

    /** セッションID */
    private String sid;
    
    /** ユーザ情報 */
    private User user;
    
    /** セッション生成時間 */
    private Date createdTime;
    
    /** 最終アクセス時間 */
    private Date lastAccessedTime;
    
    /**
     * セッション情報の初期設定を行う。
     * セッションID、ユーザ情報を設定し、
     * 現在時刻をセッション生成時間および最終アクセス時間とする。
     * 
     * @param user ユーザ情報
     */
    SimpleSession(User user) {
        this.sid = SecureIDGenerator.createID(this);
        this.user = user;
        
		Date nowTime = new Date();
		createdTime = nowTime;
		lastAccessedTime = nowTime;
    }
    
	/**
	 * セッション情報のID
	 *
	 * @return セッションID
	 * @throws WorkflowException　ワークフロー関連で例外が発生した場合
	 * @see jp.co.argo21.nautica.workflow.security.Session#getID()
	 */
	public String getID() throws WorkflowException{
		
	    updateLastAccessedTime();
		return sid;
	}
	
	/**
	 * このセッションに割り付けられたユーザ情報
	 *
	 * @return ユーザ
	 * @throws WorkflowException　ワークフロー関連で例外が発生した場合
	 * @see jp.co.argo21.nautica.workflow.security.Session#getUser()
	 */
	public User getUser() throws WorkflowException {
		
	    updateLastAccessedTime();
		return user;
	}

	/**
	 * このセッション情報の生成時間
	 *
	 * @return セッション情報の生成時間
	 * @throws WorkflowException　ワークフロー関連で例外が発生した場合
	 * @see jp.co.argo21.nautica.workflow.security.Session#getCreatedTime()
	 */
	public Date getCreatedTime() throws WorkflowException {
		
		return createdTime;
	}

	/**
	 * このセッション情報への最後のアクセス時間
	 *
	 * @return 最後のアクセス時間
	 * @throws WorkflowException　ワークフロー関連で例外が発生した場合
	 * @see jp.co.argo21.nautica.workflow.security.Session#getLastAccessedTime()
	 */
	public Date getLastAccessedTime() throws WorkflowException {
		
		return lastAccessedTime;
	}
	
	/**
	 * 最終アクセス時間を更新する。
	 */
	private void updateLastAccessedTime() {
	    
	    lastAccessedTime = new Date();
	}
}

/**
 * セキュアな ID を生成するクラスである。
 *
 * @author  mmanabe(Argo 21, Corp.)
 * @version $Revision: 1.1 $
 * @since   Nautica Workflow 1.0
 */
class SecureIDGenerator {

    /**
     * '0'16個の文字列
     * <code>long</code>の16進文字列表現時に使用
     */
    private static final String ZERO16 = "0000000000000000";
    
    /**
     * '0'8個の文字列
     * <code>int</code>の16進文字列表現時に使用
     */
    private static final String ZERO8  = "00000000";
        
    /** 乱数ジェネレータ */
  	private static SecureRandom seeder = new SecureRandom();
    
    /**
     * セキュアな ID を生成する。
     * 
     * @param   obj     ID 付与対象オブジェクト
     * @return  セキュアな ID
     */
    public static synchronized String createID(Object obj) {
        /* 実装方法は、次のサイトの 64p 〜 65p を参照した。 */
        /* <http://www-6.ibm.com/jp/software/websphere/developer/j2ee/pdf/4_3.pdf> */

		// 現在の時刻取得
		long currentTime = System.currentTimeMillis();
		String currentTimeStr = toHexString(currentTime);

		// ID 付与対象オブジェクトのハッシュコード取得
		String hashCodeStr = toHexString(System.identityHashCode(obj)); 

        // 乱数を生成
		String randomStr = toHexString(seeder.nextInt());
		
		// セキュアな ID を生成
        String secureID = currentTimeStr + hashCodeStr + randomStr;

		return secureID;
    }
    
    /**
     * 指定された整数型の16進表現文字列を取得する。
     * 
     * 指定された整数型の16進表現が8バイトに満たない場合、
     * 不足分だけ頭に0が付加される。
     * 
     * @param   num     整数
     * @return  16進表現文字列
     */
    private static String toHexString(int num)
    {
        String hexStr = Integer.toHexString(num);
        String zeroStr = ZERO8.substring(0, 8 - hexStr.length());
        
        return zeroStr + hexStr;
    }

    /**
     * 指定された長整数型の16進表現文字列を取得する。
     * 
     * 指定された長整数型の16進表現が16バイトに満たない場合、
     * 不足分だけ頭に0が付加される。
     * 
     * @param   num     長整数
     * @return  16進表現文字列
     */
    private static String toHexString(long num)
    {
        String hexStr = Long.toHexString(num);
        String zeroStr = ZERO16.substring(0, 16 - hexStr.length());
        
        return zeroStr + hexStr;
    }
}